From 9b526a0365c3b60ddf0533b5d083332646fbb50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Calvi=C3=B1o=20S=C3=A1nchez?= Date: Tue, 16 Jul 2024 14:12:54 +0200 Subject: [PATCH] feat: Update call flags by federated participants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Calviño Sánchez --- appinfo/routes/routesCallController.php | 2 + lib/Controller/CallController.php | 40 +++++++++++++++++ .../TalkV1/Controller/CallController.php | 37 ++++++++++++++++ .../features/federation/call.feature | 43 +++++++++++++++++++ 4 files changed, 122 insertions(+) diff --git a/appinfo/routes/routesCallController.php b/appinfo/routes/routesCallController.php index 286e40f282..fb260175f7 100644 --- a/appinfo/routes/routesCallController.php +++ b/appinfo/routes/routesCallController.php @@ -25,6 +25,8 @@ return [ ['name' => 'Call#sipDialOut', 'url' => '/api/{apiVersion}/call/{token}/dialout/{attendeeId}', 'verb' => 'POST', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\CallController::updateCallFlags() */ ['name' => 'Call#updateCallFlags', 'url' => '/api/{apiVersion}/call/{token}', 'verb' => 'PUT', 'requirements' => $requirements], + /** @see \OCA\Talk\Controller\CallController::updateFederatedCallFlags() */ + ['name' => 'Call#updateFederatedCallFlags', 'url' => '/api/{apiVersion}/call/{token}/federation', 'verb' => 'PUT', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\CallController::leaveCall() */ ['name' => 'Call#leaveCall', 'url' => '/api/{apiVersion}/call/{token}', 'verb' => 'DELETE', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\CallController::leaveFederatedCall() */ diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index a41ea4fb37..d6c8a108de 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -313,6 +313,7 @@ class CallController extends AEnvironmentAwareController { * 400: Updating in-call flags is not possible * 404: Call session not found */ + #[FederationSupported] #[PublicPage] #[RequireParticipant] public function updateCallFlags(int $flags): DataResponse { @@ -321,6 +322,12 @@ class CallController extends AEnvironmentAwareController { return new DataResponse([], Http::STATUS_NOT_FOUND); } + if ($this->room->isFederatedConversation()) { + /** @var \OCA\Talk\Federation\Proxy\TalkV1\Controller\CallController $proxy */ + $proxy = \OCP\Server::get(\OCA\Talk\Federation\Proxy\TalkV1\Controller\CallController::class); + return $proxy->updateFederatedCallFlags($this->room, $this->participant, $flags); + } + try { $this->participantService->updateCallFlags($this->room, $this->participant, $flags); } catch (\Exception $exception) { @@ -330,6 +337,39 @@ class CallController extends AEnvironmentAwareController { return new DataResponse(); } + /** + * Update the in-call flags on the host server using the session id of the + * federated user. + * + * @param string $sessionId Federated session id to update the flags with + * @param int<0, 15> $flags New flags + * @psalm-param int-mask-of $flags New flags + * @return DataResponse, array{}>|DataResponse + * + * 200: In-call flags updated successfully + * 400: Updating in-call flags is not possible + * 404: Call session not found + */ + #[PublicPage] + #[RequireFederatedParticipant] + #[BruteForceProtection(action: 'talkFederationAccess')] + #[BruteForceProtection(action: 'talkRoomToken')] + public function updateFederatedCallFlags(string $sessionId, int $flags): DataResponse { + if (!$this->federationAuthenticator->isFederationRequest()) { + $response = new DataResponse(null, Http::STATUS_NOT_FOUND); + $response->throttle(['token' => $this->room->getToken(), 'action' => 'talkRoomToken']); + return $response; + } + + try { + $this->participantService->updateCallFlags($this->room, $this->participant, $flags); + } catch (\Exception) { + return new DataResponse([], Http::STATUS_BAD_REQUEST); + } + + return new DataResponse(); + } + /** * Leave a call * diff --git a/lib/Federation/Proxy/TalkV1/Controller/CallController.php b/lib/Federation/Proxy/TalkV1/Controller/CallController.php index e0f4f0b712..59b9ca98b4 100644 --- a/lib/Federation/Proxy/TalkV1/Controller/CallController.php +++ b/lib/Federation/Proxy/TalkV1/Controller/CallController.php @@ -71,6 +71,43 @@ class CallController { return new DataResponse([], $statusCode); } + /** + * @see \OCA\Talk\Controller\RoomController::updateFederatedCallFlags() + * + * @param Room $room the federated room to update the call flags in + * @param Participant $participant the federated user to update the call + * flags; the participant must have a session + * @param int<0, 15> $flags New flags + * @psalm-param int-mask-of $flags New flags + * @return DataResponse, array{}> + * @throws CannotReachRemoteException + * + * 200: In-call flags updated successfully for federated user + * 400: Updating in-call flags is not possible + * 404: Room not found + */ + public function updateFederatedCallFlags(Room $room, Participant $participant, int $flags): DataResponse { + $options = [ + 'sessionId' => $participant->getSession()->getSessionId(), + 'flags' => $flags, + ]; + + $proxy = $this->proxy->put( + $participant->getAttendee()->getInvitedCloudId(), + $participant->getAttendee()->getAccessToken(), + $room->getRemoteServer() . '/ocs/v2.php/apps/spreed/api/v4/call/' . $room->getRemoteToken() . '/federation', + $options, + ); + + $statusCode = $proxy->getStatusCode(); + if (!in_array($statusCode, [Http::STATUS_OK, Http::STATUS_BAD_REQUEST, Http::STATUS_NOT_FOUND], true)) { + $this->proxy->logUnexpectedStatusCode(__METHOD__, $proxy->getStatusCode()); + throw new CannotReachRemoteException(); + } + + return new DataResponse([], $statusCode); + } + /** * @see \OCA\Talk\Controller\RoomController::leaveFederatedCall() * diff --git a/tests/integration/features/federation/call.feature b/tests/integration/features/federation/call.feature index 832f959398..620a76c334 100644 --- a/tests/integration/features/federation/call.feature +++ b/tests/integration/features/federation/call.feature @@ -54,6 +54,49 @@ Feature: federation/call | federated_users | participant1@{$LOCAL_URL} | 3 | | users | participant2 | 7 | + Scenario: update call flags + Given user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds federated_user "participant2@REMOTE" to room "room" with 200 (v4) + And using server "REMOTE" + And user "participant2" has the following invitations (v1) + | remoteServerUrl | remoteToken | state | inviterCloudId | inviterDisplayName | + | LOCAL | room | 0 | participant1@http://localhost:8080 | participant1-displayname | + And user "participant2" accepts invite to room "room" of server "LOCAL" with 200 (v1) + | id | name | type | remoteServer | remoteToken | + | LOCAL::room | room | 2 | LOCAL | room | + And using server "LOCAL" + And user "participant1" joins room "room" with 200 (v4) + And using server "REMOTE" + And user "participant2" joins room "LOCAL::room" with 200 (v4) + And user "participant2" joins call "LOCAL::room" with 200 (v4) + | flags | 7 | + And user "participant2" is participant of room "LOCAL::room" (v4) + | callFlag | + | 7 | + And user "participant2" sees the following attendees in room "LOCAL::room" with 200 (v4) + | actorType | actorId | inCall | + | federated_users | participant1@{$LOCAL_URL} | 0 | + | users | participant2 | 7 | + When user "participant2" updates call flags in room "LOCAL::room" to "1" with 200 (v4) + And using server "LOCAL" + And user "participant1" is participant of room "room" (v4) + | callFlag | + | 7 | + And user "participant1" sees the following attendees in room "room" with 200 (v4) + | actorType | actorId | inCall | + | users | participant1 | 0 | + | federated_users | participant2@{$REMOTE_URL} | 1 | + And using server "REMOTE" + And user "participant2" is participant of room "LOCAL::room" (v4) + | callFlag | + | 7 | + And user "participant2" sees the following attendees in room "LOCAL::room" with 200 (v4) + | actorType | actorId | inCall | + | federated_users | participant1@{$LOCAL_URL} | 0 | + | users | participant2 | 1 | + Scenario: leave call Given user "participant1" creates room "room" (v4) | roomType | 2 |