diff options
-rw-r--r-- | lib/Controller/PageController.php | 2 | ||||
-rw-r--r-- | lib/Controller/RoomController.php | 15 | ||||
-rw-r--r-- | lib/Manager.php | 35 | ||||
-rw-r--r-- | lib/Middleware/InjectionMiddleware.php | 10 | ||||
-rw-r--r-- | lib/Room.php | 69 | ||||
-rw-r--r-- | lib/Service/ParticipantService.php | 12 | ||||
-rw-r--r-- | lib/Share/RoomShareProvider.php | 2 | ||||
-rw-r--r-- | lib/Signaling/BackendNotifier.php | 1 | ||||
-rw-r--r-- | tests/php/Controller/SignalingControllerTest.php | 12 |
9 files changed, 106 insertions, 52 deletions
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index c5a3b36a6..8f1d12c27 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -216,7 +216,7 @@ class PageController extends Controller { if ($room instanceof Room && $room->hasPassword()) { // If the user joined themselves or is not found, they need the password. try { - $participant = $room->getParticipant($this->userId); + $participant = $room->getParticipant($this->userId, false); $requirePassword = $participant->getAttendee()->getParticipantType() === Participant::USER_SELF_JOINED; } catch (ParticipantNotFoundException $e) { $requirePassword = true; diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index a0b6031e7..0676fe617 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -264,14 +264,15 @@ class RoomController extends AEnvironmentAwareController { $includeLastMessage = !$isSIPBridgeRequest; try { - $room = $this->manager->getRoomForUserByToken($token, $this->userId, $includeLastMessage, $isSIPBridgeRequest); + $sessionId = $this->session->getSessionForRoom($token); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId, $includeLastMessage, $isSIPBridgeRequest); $participant = null; try { $participant = $room->getParticipant($this->userId); } catch (ParticipantNotFoundException $e) { try { - $participant = $room->getParticipantBySession($this->session->getSessionForRoom($token)); + $participant = $room->getParticipantBySession($sessionId); } catch (ParticipantNotFoundException $e) { } } @@ -1568,8 +1569,9 @@ class RoomController extends AEnvironmentAwareController { * @return DataResponse */ public function joinRoom(string $token, string $password = '', bool $force = true): DataResponse { + $sessionId = $this->session->getSessionForRoom($token); try { - $room = $this->manager->getRoomForUserByToken($token, $this->userId); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); } catch (RoomNotFoundException $e) { return new DataResponse([], Http::STATUS_NOT_FOUND); } @@ -1585,9 +1587,8 @@ class RoomController extends AEnvironmentAwareController { } catch (ParticipantNotFoundException $e) { } } else { - $sessionForToken = $this->session->getSessionForRoom($token); try { - $previousParticipant = $room->getParticipantBySession($sessionForToken); + $previousParticipant = $room->getParticipantBySession($sessionId); $previousSession = $previousParticipant->getSession(); } catch (ParticipantNotFoundException $e) { } @@ -1595,7 +1596,7 @@ class RoomController extends AEnvironmentAwareController { if ($previousSession instanceof Session && $previousSession->getSessionId() !== '0') { if ($force === false && $previousSession->getInCall() !== Participant::FLAG_DISCONNECTED) { - // Previous session was active in the call, show a warning + // Previous session is/was active in the call, show a warning return new DataResponse([ 'sessionId' => $previousSession->getSessionId(), 'inCall' => $previousSession->getInCall(), @@ -1672,7 +1673,7 @@ class RoomController extends AEnvironmentAwareController { $this->session->removeSessionForRoom($token); try { - $room = $this->manager->getRoomForUserByToken($token, $this->userId); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); $participant = $room->getParticipantBySession($sessionId); $this->participantService->leaveRoomAsSession($room, $participant); } catch (RoomNotFoundException $e) { diff --git a/lib/Manager.php b/lib/Manager.php index fa23f4ade..8795b056a 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -303,6 +303,7 @@ class Manager { * @return Room[] */ public function getRoomsForUser(string $userId, bool $includeLastMessage = false): array { + // FIXME hand in a list of sessions or how do we want to do it here? $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectRoomsTable($query); @@ -391,9 +392,6 @@ class Manager { $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()->isNull('a.id')) ->andWhere($query->expr()->in('r.type', $query->createNamedParameter($allowedRoomTypes, IQueryBuilder::PARAM_INT_ARRAY))) ->andWhere($query->expr()->in('r.listable', $query->createNamedParameter($allowedListedTypes, IQueryBuilder::PARAM_INT_ARRAY))); @@ -435,15 +433,11 @@ class Manager { if ($userId !== null) { // Non guest user $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->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(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')); } @@ -483,12 +477,13 @@ class Manager { * * @param string $token * @param string|null $userId + * @param string|null $sessionId * @param bool $includeLastMessage * @param bool $isSIPBridgeRequest * @return Room * @throws RoomNotFoundException */ - public function getRoomForUserByToken(string $token, ?string $userId, bool $includeLastMessage = false, bool $isSIPBridgeRequest = false): Room { + public function getRoomForUserByToken(string $token, ?string $userId, ?string $sessionId = null, bool $includeLastMessage = false, bool $isSIPBridgeRequest = false): Room { $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectRoomsTable($query); @@ -499,15 +494,18 @@ class Manager { if ($userId !== null) { // Non guest user $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->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(Attendee::ACTOR_USERS)), $query->expr()->eq('a.room_id', 'r.id') - )) - ->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + )); + if ($sessionId !== null) { + $helper->selectSessionsTable($query); + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), $query->expr()->eq('a.id', 's.attendee_id') )); + } } if ($includeLastMessage) { @@ -584,26 +582,31 @@ class Manager { * @param string $token * @param string $actorType * @param string $actorId + * @param string|null $sessionId * @return Room * @throws RoomNotFoundException */ - public function getRoomByActor(string $token, string $actorType, string $actorId): Room { + public function getRoomByActor(string $token, string $actorType, string $actorId, ?string $sessionId = null): Room { $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectRoomsTable($query); $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->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 ($sessionId !== null) { + $helper->selectSessionsTable($query); + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), + $query->expr()->eq('a.id', 's.attendee_id') + )); + } + $result = $query->execute(); $row = $result->fetch(); $result->closeCursor(); diff --git a/lib/Middleware/InjectionMiddleware.php b/lib/Middleware/InjectionMiddleware.php index 9d099d697..07ec777ec 100644 --- a/lib/Middleware/InjectionMiddleware.php +++ b/lib/Middleware/InjectionMiddleware.php @@ -119,7 +119,7 @@ class InjectionMiddleware extends Middleware { */ protected function getRoom(AEnvironmentAwareController $controller): void { $token = $this->request->getParam('token'); - $room = $this->manager->getRoomByToken($token, $this->userId); + $room = $this->manager->getRoomByToken($token); $controller->setRoom($room); } @@ -130,7 +130,8 @@ class InjectionMiddleware extends Middleware { */ protected function getLoggedIn(AEnvironmentAwareController $controller, bool $moderatorRequired): void { $token = $this->request->getParam('token'); - $room = $this->manager->getRoomForUserByToken($token, $this->userId); + $sessionId = $this->talkSession->getSessionForRoom($token); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); $controller->setRoom($room); $participant = $room->getParticipant($this->userId); @@ -149,13 +150,14 @@ class InjectionMiddleware extends Middleware { */ protected function getLoggedInOrGuest(AEnvironmentAwareController $controller, bool $moderatorRequired): void { $token = $this->request->getParam('token'); - $room = $this->manager->getRoomForUserByToken($token, $this->userId); + $sessionId = $this->talkSession->getSessionForRoom($token); + $room = $this->manager->getRoomForUserByToken($token, $this->userId, $sessionId); $controller->setRoom($room); - $sessionId = $this->talkSession->getSessionForRoom($token); if ($sessionId !== null) { $participant = $room->getParticipantBySession($sessionId); } else { + // FIXME is this still needed? Maybe for users joining public links? $participant = $room->getParticipant($this->userId); } $controller->setParticipant($participant); diff --git a/lib/Room.php b/lib/Room.php index c91c80857..d85214910 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -35,6 +35,7 @@ use OCA\Talk\Events\VerifyRoomPasswordEvent; use OCA\Talk\Exceptions\ParticipantNotFoundException; use OCA\Talk\Model\Attendee; use OCA\Talk\Model\SelectHelper; +use OCA\Talk\Model\Session; use OCA\Talk\Service\ParticipantService; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Comments\IComment; @@ -402,28 +403,46 @@ class Room { /** * @param string|null $userId + * @param string|null|false $sessionId Set to false if you don't want to load a session (and save resources), + * string to try loading a specific session + * null to try loading "any" * @return Participant * @throws ParticipantNotFoundException When the user is not a participant */ - public function getParticipant(?string $userId): Participant { + public function getParticipant(?string $userId, $sessionId = null): Participant { if (!is_string($userId) || $userId === '') { throw new ParticipantNotFoundException('Not a user'); } if ($this->currentUser === $userId && $this->participant instanceof Participant) { - return $this->participant; + if (!$sessionId + || ($this->participant->getSession() instanceof Session + && $this->participant->getSession()->getSessionId() === $sessionId)) { + return $this->participant; + } } $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->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(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); + + if ($sessionId !== false) { + $helper->selectSessionsTable($query); + if ($sessionId !== null) { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), + $query->expr()->eq('a.id', 's.attendee_id') + )); + } else { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); + } + } + $result = $query->execute(); $row = $result->fetch(); $result->closeCursor(); @@ -479,9 +498,7 @@ class Room { $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->from('talk_attendees', 'a') - ->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')) ->andWhere($query->expr()->eq('a.pin', $query->createNamedParameter($pin))) ->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId()))) ->setMaxResults(1); @@ -498,19 +515,33 @@ class Room { /** * @param int $attendeeId + * @param string|null|false $sessionId Set to false if you don't want to load a session (and save resources), + * string to try loading a specific session + * null to try loading "any" * @return Participant * @throws ParticipantNotFoundException When the pin is not valid (has no participant assigned) */ - public function getParticipantByAttendeeId(int $attendeeId): Participant { + public function getParticipantByAttendeeId(int $attendeeId, $sessionId = null): Participant { $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); $query->from('talk_attendees', 'a') - ->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')) ->andWhere($query->expr()->eq('a.id', $query->createNamedParameter($attendeeId, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId()))) ->setMaxResults(1); + + if ($sessionId !== false) { + $helper->selectSessionsTable($query); + if ($sessionId !== null) { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), + $query->expr()->eq('a.id', 's.attendee_id') + )); + } else { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); + } + } + $result = $query->execute(); $row = $result->fetch(); $result->closeCursor(); @@ -525,24 +556,38 @@ class Room { /** * @param string $actorType * @param string $actorId + * @param string|null|false $sessionId Set to false if you don't want to load a session (and save resources), + * string to try loading a specific session + * null to try loading "any" * @return Participant * @throws ParticipantNotFoundException When the pin is not valid (has no participant assigned) */ - public function getParticipantByActor(string $actorType, string $actorId): Participant { + public function getParticipantByActor(string $actorType, string $actorId, $sessionId = null): Participant { if ($actorType === Attendee::ACTOR_USERS) { return $this->getParticipant($actorId); } $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); - $helper->selectAttendeesTable($query); $helper->selectSessionsTable($query); $query->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); + + if ($sessionId !== false) { + $helper->selectSessionsTable($query); + if ($sessionId !== null) { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( + $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), + $query->expr()->eq('a.id', 's.attendee_id') + )); + } else { + $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); + } + } + $result = $query->execute(); $row = $result->fetch(); $result->closeCursor(); diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 6a20eb323..a788d009c 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -586,6 +586,7 @@ class ParticipantService { * @return Participant[] */ public function getParticipantsForRoom(Room $room): array { + // FIXME Need to make sure a user is skipped when at least one session is in the call $query = $this->connection->getQueryBuilder(); $helper = new SelectHelper(); @@ -665,6 +666,7 @@ class ParticipantService { $helper->selectAttendeesTable($query); $helper->selectSessionsTable($query); $query->from('talk_attendees', 'a') + // Currently we only care if the user has a session at all, so we can select any: #ThisIsFine ->leftJoin( 'a', 'talk_sessions', 's', $query->expr()->eq('s.attendee_id', 'a.id') @@ -739,14 +741,14 @@ class ParticipantService { ->from('talk_attendees', 'a') ->leftJoin( 'a', 'talk_sessions', 's', - $query->expr()->eq('s.attendee_id', 'a.id') + $query->expr()->andX( + $query->expr()->eq('s.attendee_id', 'a.id'), + $query->expr()->neq('s.in_call', $query->createNamedParameter(Participant::FLAG_DISCONNECTED)), + ) ) ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) ->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') - )); + ->andWhere($query->expr()->isNull('s.in_call')); $userIds = []; $result = $query->execute(); diff --git a/lib/Share/RoomShareProvider.php b/lib/Share/RoomShareProvider.php index 34cbd0d13..e2958b1b7 100644 --- a/lib/Share/RoomShareProvider.php +++ b/lib/Share/RoomShareProvider.php @@ -173,7 +173,7 @@ class RoomShareProvider implements IShareProvider { } try { - $room->getParticipant($share->getSharedBy()); + $room->getParticipant($share->getSharedBy(), false); } catch (ParticipantNotFoundException $e) { // If the sharer is not a participant of the room even if the room // exists the error is still "Room not found". diff --git a/lib/Signaling/BackendNotifier.php b/lib/Signaling/BackendNotifier.php index a1ec48532..1a155157f 100644 --- a/lib/Signaling/BackendNotifier.php +++ b/lib/Signaling/BackendNotifier.php @@ -251,6 +251,7 @@ class BackendNotifier { $this->logger->info('Room participants modified: ' . $room->getToken() . ' ' . print_r($sessionIds, true)); $changed = []; $users = []; + // FIXME needs to select session and left join attendees instead! $participants = $this->participantService->getParticipantsForRoom($room); foreach ($participants as $participant) { $attendee = $participant->getAttendee(); diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index 2dc9453db..47bf31571 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -919,7 +919,7 @@ class SignalingControllerTest extends \Test\TestCase { // The user joined the room. $oldParticipant = $participantService->joinRoom($room, $testUser, ''); $oldSessionId = $oldParticipant->getSession()->getSessionId(); - $result = $this->performBackendRequest([ + $this->performBackendRequest([ 'type' => 'room', 'room' => [ 'roomid' => $room->getToken(), @@ -928,14 +928,14 @@ class SignalingControllerTest extends \Test\TestCase { 'action' => 'join', ], ]); - $participant = $room->getParticipant($this->userId); + $participant = $room->getParticipant($this->userId, $oldSessionId); $this->assertEquals($oldSessionId, $participant->getSession()->getSessionId()); // The user is reloading the browser which will join him with another // session id. $newParticipant = $participantService->joinRoom($room, $testUser, ''); $newSessionId = $newParticipant->getSession()->getSessionId(); - $result = $this->performBackendRequest([ + $this->performBackendRequest([ 'type' => 'room', 'room' => [ 'roomid' => $room->getToken(), @@ -946,11 +946,11 @@ class SignalingControllerTest extends \Test\TestCase { ]); // Now the new session id is stored in the database. - $participant = $room->getParticipant($this->userId); + $participant = $room->getParticipant($this->userId, $newSessionId); $this->assertEquals($newSessionId, $participant->getSession()->getSessionId()); // Leaving the old session id... - $result = $this->performBackendRequest([ + $this->performBackendRequest([ 'type' => 'room', 'room' => [ 'roomid' => $room->getToken(), @@ -961,7 +961,7 @@ class SignalingControllerTest extends \Test\TestCase { ]); // ...will keep the new session id in the database. - $participant = $room->getParticipant($this->userId); + $participant = $room->getParticipant($this->userId, $newSessionId); $this->assertEquals($newSessionId, $participant->getSession()->getSessionId()); } } |