diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index f44371f8ccb..3ee882672cb 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -1660,6 +1660,10 @@ public function joinRoom(string $token, string $password = '', bool $force = tru return new DataResponse([], Http::STATUS_NOT_FOUND); } + /** @var TalkRoom $data */ + $data = $response->getData(); + + $proxyHeaders = $response->getHeaders(); if (isset($proxyHeaders['X-Nextcloud-Talk-Proxy-Hash'])) { $headers['X-Nextcloud-Talk-Proxy-Hash'] = $proxyHeaders['X-Nextcloud-Talk-Proxy-Hash']; @@ -1675,8 +1679,8 @@ public function joinRoom(string $token, string $password = '', bool $force = tru * The session id can be null only for requests from Talk < 20. * * @param string $token Token of the room - * @param string $sessionId Federated session id to join with - * @return DataResponse, array{X-Nextcloud-Talk-Hash: string}>|DataResponse + * @param ?string $sessionId Federated session id to join with + * @return DataResponse|DataResponse * * 200: Federated user joined the room * 404: Room not found @@ -1711,14 +1715,16 @@ public function joinFederatedRoom(string $token, ?string $sessionId): DataRespon if ($session instanceof Session) { $this->sessionService->updateLastPing($session, $this->timeFactory->getTime()); } + } else { + $participant = $this->participantService->getParticipantByActor($room, Attendee::ACTOR_FEDERATED_USERS, $this->federationAuthenticator->getCloudId()); } // Let the clients know if they need to reload capabilities $capabilities = $this->capabilities->getCapabilities(); - return new DataResponse([], Http::STATUS_OK, [ + return new DataResponse($this->formatRoom($room, $participant), Http::STATUS_OK, [ 'X-Nextcloud-Talk-Hash' => sha1(json_encode($capabilities)), ]); - } catch (RoomNotFoundException|UnauthorizedException) { + } catch (RoomNotFoundException|ParticipantNotFoundException|UnauthorizedException) { $response = new DataResponse(null, Http::STATUS_NOT_FOUND); $response->throttle(['token' => $token, 'action' => 'talkFederationAccess']); return $response; diff --git a/lib/Federation/Proxy/TalkV1/Controller/RoomController.php b/lib/Federation/Proxy/TalkV1/Controller/RoomController.php index 963e3eb2da2..651719f7aac 100644 --- a/lib/Federation/Proxy/TalkV1/Controller/RoomController.php +++ b/lib/Federation/Proxy/TalkV1/Controller/RoomController.php @@ -91,7 +91,12 @@ public function joinFederatedRoom(Room $room, Participant $participant): DataRes $headers = ['X-Nextcloud-Talk-Proxy-Hash' => $this->proxy->overwrittenRemoteTalkHash($proxy->getHeader('X-Nextcloud-Talk-Hash'))]; - return new DataResponse([], $statusCode, $headers); + /** @var TalkRoom[] $data */ + $data = $this->proxy->getOCSData($proxy); + + $data = $this->userConverter->convertAttendee($room, $data, 'actorType', 'actorId', 'displayName'); + + return new DataResponse($data, $statusCode, $headers); } /** diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php index cfd1abd99d0..22b79f4ce8d 100644 --- a/lib/Service/RoomService.php +++ b/lib/Service/RoomService.php @@ -28,6 +28,7 @@ use OCA\Talk\Model\Attendee; use OCA\Talk\Model\BreakoutRoom; use OCA\Talk\Participant; +use OCA\Talk\ResponseDefinitions; use OCA\Talk\Room; use OCA\Talk\Webinary; use OCP\AppFramework\Utility\ITimeFactory; @@ -43,6 +44,9 @@ use OCP\Security\IHasher; use OCP\Share\IManager as IShareManager; +/** + * @psalm-import-type TalkRoom from ResponseDefinitions + */ class RoomService { public function __construct( @@ -429,7 +433,8 @@ public function setAvatar(Room $room, string $avatar): bool { * @throws InvalidArgumentException When trying to start */ public function setCallRecording(Room $room, int $status = Room::RECORDING_NONE, ?Participant $participant = null): void { - if (!$this->config->isRecordingEnabled() && $status !== Room::RECORDING_NONE) { + $syncFederatedRoom = $room->getRemoteServer() && $room->getRemoteToken(); + if (!$syncFederatedRoom && !$this->config->isRecordingEnabled() && $status !== Room::RECORDING_NONE) { throw new InvalidArgumentException('config'); } @@ -993,6 +998,101 @@ public function setLastActivity(Room $room, \DateTime $now): void { $room->setLastActivity($now); } + /** + * @param Room $localRoom + * @param TalkRoom $host + * @return void + */ + public function syncPropertiesFromHostRoom(Room $local, array $host): void { + $update = $this->db->getQueryBuilder(); + $update->update('talk_rooms') + ->where($update->expr()->eq('id', $update->createNamedParameter($local->getId(), IQueryBuilder::PARAM_INT))); + + if (isset($host['type']) && $host['type'] !== $local->getType()) { + $local->setType($host['type']); + $update->set('type', $update->createNamedParameter($host['type'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['name']) && $host['name'] !== $local->getName()) { + $local->setName($host['name']); + $update->set('name', $update->createNamedParameter($host['name'])); + $changed = true; + } + if (isset($host['description']) && $host['description'] !== $local->getDescription()) { + $local->setDescription($host['description']); + $update->set('description', $update->createNamedParameter($host['description'])); + $changed = true; + } + if (isset($host['callRecording']) && $host['callRecording'] !== $local->getCallRecording()) { + $local->setCallRecording($host['callRecording']); + $update->set('call_recording', $update->createNamedParameter($host['callRecording'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['defaultPermissions']) && $host['defaultPermissions'] !== $local->getDefaultPermissions()) { + $local->setDefaultPermissions($host['defaultPermissions']); + $update->set('default_permissions', $update->createNamedParameter($host['defaultPermissions'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['avatarVersion']) && $host['avatarVersion'] !== $local->getAvatar()) { + $local->setAvatar($host['avatarVersion']); + $update->set('avatar', $update->createNamedParameter($host['avatarVersion'])); // FIXME breaking .jpg? + $changed = true; + } + if (isset($host['lastActivity']) && $host['lastActivity'] !== $local->getLastActivity()) { // FIXME DateTime|null vs int + $local->setLastActivity($host['lastActivity']); // FIXME DateTime|null vs int + } + if (isset($host['lobbyState']) && $host['lobbyState'] !== $local->getLobbyState(false)) { + $local->setLobbyState($host['lobbyState']); + $update->set('lobby_state', $update->createNamedParameter($host['lobbyState'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['lobbyTimer']) && $host['lobbyTimer'] !== $local->getLobbyTimer(false)) { // FIXME DateTime|null vs int + $local->setLobbyTimer($host['lobbyTimer']); // FIXME DateTime|null vs int + } + if (isset($host['callStartTime'], $host['callFlag']) && ( + $host['callStartTime'] !== $local->getActiveSince() // FIXME DateTime|null vs int + || $host['callFlag'] !== $local->getCallFlag() + )) { + $local->setActiveSince($host['callStartTime'], $host['callFlag']); // FIXME DateTime|null vs int + } + if (isset($host['mentionPermissions']) && $host['mentionPermissions'] !== $local->getMentionPermissions()) { + $local->setMentionPermissions($host['mentionPermissions']); + $update->set('mention_permissions', $update->createNamedParameter($host['mentionPermissions'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['messageExpiration']) && $host['messageExpiration'] !== $local->getMessageExpiration()) { + $local->setMessageExpiration($host['messageExpiration']); + $update->set('message_expiration', $update->createNamedParameter($host['messageExpiration'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['readOnly']) && $host['readOnly'] !== $local->getReadOnly()) { + $local->setReadOnly($host['readOnly']); + $update->set('read_only', $update->createNamedParameter($host['readOnly'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['recordingConsent']) && $host['recordingConsent'] !== $local->getRecordingConsent()) { + $local->setRecordingConsent($host['recordingConsent']); + $update->set('recording_consent', $update->createNamedParameter($host['recordingConsent'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + if (isset($host['sipEnabled']) && $host['sipEnabled'] !== $local->getSIPEnabled()) { + $local->setSIPEnabled($host['sipEnabled']); + $update->set('sip_enabled', $update->createNamedParameter($host['sipEnabled'], IQueryBuilder::PARAM_INT)); + $changed = true; + } + // Ignore for now, so the conversation is not found by other users on this fedederated participants server + // if (isset($host['listable']) && $host['listable'] !== $local->getListable()) { + // $local->setListable($host['listable']); + // $update->set('listable', $update->createNamedParameter($host['listable'], IQueryBuilder::PARAM_INT)); + // } + + if ($changed) { + $update->executeStatement(); + } + + // FIXME trigger events? + } + public function deleteRoom(Room $room): void { $event = new BeforeRoomDeletedEvent($room); $this->dispatcher->dispatchTyped($event);