Browse Source

Prepare selecting the correct session in case there are multiple

Signed-off-by: Joas Schilling <coding@schilljs.com>
pull/5194/head
Joas Schilling 5 years ago
parent
commit
4031c182df
No known key found for this signature in database GPG Key ID: 7076EA9751AACDDA
  1. 2
      lib/Controller/PageController.php
  2. 15
      lib/Controller/RoomController.php
  3. 35
      lib/Manager.php
  4. 10
      lib/Middleware/InjectionMiddleware.php
  5. 69
      lib/Room.php
  6. 12
      lib/Service/ParticipantService.php
  7. 2
      lib/Share/RoomShareProvider.php
  8. 1
      lib/Signaling/BackendNotifier.php
  9. 12
      tests/php/Controller/SignalingControllerTest.php

2
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;

15
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) {

35
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();

10
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);

69
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();

12
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();

2
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".

1
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();

12
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());
}
}
Loading…
Cancel
Save