Skip to content

Commit

Permalink
fix(federation): Sync room properties on join
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <[email protected]>
  • Loading branch information
nickvergessen committed Aug 21, 2024
1 parent 68b8315 commit 7272768
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 6 deletions.
14 changes: 10 additions & 4 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand All @@ -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<Http::STATUS_OK, array<empty>, array{X-Nextcloud-Talk-Hash: string}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
* @param ?string $sessionId Federated session id to join with
* @return DataResponse<Http::STATUS_OK, TalkRoom, array{X-Nextcloud-Talk-Hash: string}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: Federated user joined the room
* 404: Room not found
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion lib/Federation/Proxy/TalkV1/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
102 changes: 101 additions & 1 deletion lib/Service/RoomService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(
Expand Down Expand Up @@ -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');
}

Expand Down Expand Up @@ -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

Check failure on line 1042 in lib/Service/RoomService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

InvalidArgument

lib/Service/RoomService.php:1042:28: InvalidArgument: Argument 1 of OCA\Talk\Room::setLastActivity expects DateTime, but int provided (see https://psalm.dev/004)
}
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

Check failure on line 1050 in lib/Service/RoomService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

InvalidArgument

lib/Service/RoomService.php:1050:26: InvalidArgument: Argument 1 of OCA\Talk\Room::setLobbyTimer expects DateTime|null, but int provided (see https://psalm.dev/004)
}
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

Check failure on line 1056 in lib/Service/RoomService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

InvalidArgument

lib/Service/RoomService.php:1056:27: InvalidArgument: Argument 1 of OCA\Talk\Room::setActiveSince expects DateTime, but int provided (see https://psalm.dev/004)
}
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);
Expand Down

0 comments on commit 7272768

Please sign in to comment.