diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index f9f1446115bf..f9cc67714ee9 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -28,6 +28,7 @@ use OCA\Talk\Chat\ChatManager; use OCA\Talk\Events\MessageParseEvent; use OCA\Talk\Exceptions\ParticipantNotFoundException; +use OCA\Talk\Federation\Authenticator; use OCA\Talk\GuestManager; use OCA\Talk\Model\Attendee; use OCA\Talk\Model\Message; @@ -77,6 +78,9 @@ class SystemMessage implements IEventListener { /** @var array> */ protected array $phoneNames = []; + + protected array $currentFederatedUserDetails = []; + public function __construct( protected IUserManager $userManager, protected IGroupManager $groupManager, @@ -89,6 +93,7 @@ public function __construct( protected ICloudIdManager $cloudIdManager, protected IURLGenerator $url, protected FilesMetadataCache $metadataCache, + protected Authenticator $federationAuthenticator, ) { } @@ -135,6 +140,19 @@ protected function parseMessage(Message $chatMessage): void { if ($participant === null) { $currentActorId = null; $currentUserIsActor = false; + } elseif ($this->federationAuthenticator->isFederationRequest()) { + if (empty($this->currentFederatedUserDetails)) { + $cloudId = $this->cloudIdManager->resolveCloudId($this->federationAuthenticator->getCloudId()); + $this->currentFederatedUserDetails = [ + 'user' => $cloudId->getUser(), + 'server' => $cloudId->getRemote(), + ]; + } + + $currentUserIsActor = isset($parsedParameters['actor']['server']) && + $parsedParameters['actor']['type'] === 'user' && + $this->currentFederatedUserDetails['user'] === $parsedParameters['actor']['id'] && + $this->currentFederatedUserDetails['server'] === $parsedParameters['actor']['server']; } elseif (!$participant->isGuest()) { $currentActorId = $participant->getAttendee()->getActorId(); $currentUserIsActor = $parsedParameters['actor']['type'] === 'user' && @@ -338,7 +356,7 @@ protected function parseMessage(Message $chatMessage): void { } } } elseif ($message === 'federated_user_added') { - $parsedParameters['federated_user'] = $this->getRemoteUser($parameters['federated_user']); + $parsedParameters['federated_user'] = $this->getRemoteUser($room, $parameters['federated_user']); $parsedMessage = $this->l->t('{actor} invited {federated_user}'); if ($currentUserIsActor) { $parsedMessage = $this->l->t('You invited {federated_user}'); @@ -348,7 +366,7 @@ protected function parseMessage(Message $chatMessage): void { $parsedMessage = $this->l->t('{federated_user} accepted the invitation'); } } elseif ($message === 'federated_user_removed') { - $parsedParameters['federated_user'] = $this->getRemoteUser($parameters['federated_user']); + $parsedParameters['federated_user'] = $this->getRemoteUser($room, $parameters['federated_user']); $parsedMessage = $this->l->t('{actor} removed {federated_user}'); if ($currentUserIsActor) { $parsedMessage = $this->l->t('You removed {federated_user}'); @@ -647,6 +665,19 @@ protected function parseDeletedMessage(Message $chatMessage): void { if ($participant === null) { $currentUserIsActor = false; + } elseif ($this->federationAuthenticator->isFederationRequest()) { + if (empty($this->currentFederatedUserDetails)) { + $cloudId = $this->cloudIdManager->resolveCloudId($this->federationAuthenticator->getCloudId()); + $this->currentFederatedUserDetails = [ + 'user' => $cloudId->getUser(), + 'server' => $cloudId->getRemote(), + ]; + } + + $currentUserIsActor = isset($parsedParameters['actor']['server']) && + $parsedParameters['actor']['type'] === 'user' && + $this->currentFederatedUserDetails['user'] === $parsedParameters['actor']['id'] && + $this->currentFederatedUserDetails['server'] === $parsedParameters['actor']['server']; } elseif (!$participant->isGuest()) { $currentUserIsActor = $parsedParameters['actor']['type'] === 'user' && $participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS && @@ -797,7 +828,7 @@ protected function getActor(Room $room, string $actorType, string $actorId): arr return $this->getPhone($room, $actorId, ''); } if ($actorType === Attendee::ACTOR_FEDERATED_USERS) { - return $this->getRemoteUser($actorId); + return $this->getRemoteUser($room, $actorId); } return $this->getUser($actorId); @@ -827,13 +858,19 @@ protected function getUser(string $uid): array { ]; } - protected function getRemoteUser(string $federationId): array { + protected function getRemoteUser(Room $room, string $federationId): array { $cloudId = $this->cloudIdManager->resolveCloudId($federationId); + $displayName = $cloudId->getDisplayId(); + try { + $participant = $this->participantService->getParticipantByActor($room, Attendee::ACTOR_FEDERATED_USERS, $federationId); + $displayName = $participant->getAttendee()->getDisplayName(); + } catch (ParticipantNotFoundException) { + } return [ 'type' => 'user', 'id' => $cloudId->getUser(), - 'name' => $cloudId->getDisplayId(), + 'name' => $displayName, 'server' => $cloudId->getRemote(), ]; } diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index cafb44d48ccd..a6b2d540b751 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -2657,7 +2657,6 @@ protected function compareDataResponse(TableNode $formData = null) { } $expected[$i]['message'] = str_replace('\n', "\n", $expected[$i]['message']); - if (str_ends_with($expected[$i]['actorId'], '@{$BASE_URL}')) { $expected[$i]['actorId'] = str_replace('{$BASE_URL}', rtrim($this->baseUrl, '/'), $expected[$i]['actorId']); } @@ -2665,6 +2664,13 @@ protected function compareDataResponse(TableNode $formData = null) { $expected[$i]['actorId'] = str_replace('{$REMOTE_URL}', rtrim($this->baseRemoteUrl, '/'), $expected[$i]['actorId']); } + if (str_contains($expected[$i]['messageParameters'], '{$BASE_URL}')) { + $expected[$i]['messageParameters'] = str_replace('{$BASE_URL}', str_replace('/', '\/', rtrim($this->baseUrl, '/')), $expected[$i]['messageParameters']); + } + if (str_contains($expected[$i]['messageParameters'], '{$REMOTE_URL}')) { + $expected[$i]['messageParameters'] = str_replace('{$REMOTE_URL}', str_replace('/', '\/', rtrim($this->baseRemoteUrl, '/')), $expected[$i]['messageParameters']); + } + if (isset($expected[$i]['lastEditActorId'])) { if (str_ends_with($expected[$i]['lastEditActorId'], '@{$BASE_URL}')) { $expected[$i]['lastEditActorId'] = str_replace('{$BASE_URL}', rtrim($this->baseUrl, '/'), $expected[$i]['lastEditActorId']); diff --git a/tests/integration/features/federation/chat.feature b/tests/integration/features/federation/chat.feature index b8e9d730f07a..a797d15fc24a 100644 --- a/tests/integration/features/federation/chat.feature +++ b/tests/integration/features/federation/chat.feature @@ -117,14 +117,14 @@ Feature: federation/chat And user "participant2" deletes message "Message 1-1 - Edit 1" from room "LOCAL::room" with 200 Then user "participant1" sees the following messages in room "room" with 200 | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | - | room | federated_users | participant2@{$REMOTE_URL} | participant2-displayname | Message deleted by author | {"actor":{"type":"user","id":"participant2","name":"participant2@localhost:8180","server":"http:\/\/localhost:8180"}} | Message deleted by you | - | room | users | participant1 | participant1-displayname | Message deleted by you | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"}} | | + | room | federated_users | participant2@{$REMOTE_URL} | participant2-displayname | Message deleted by author | {"actor":{"type":"user","id":"participant2","name":"participant2-displayname","server":"{$REMOTE_URL}"}} | Message deleted by you | + | room | users | participant1 | participant1-displayname | Message deleted by you | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"}} | | When next message request has the following parameters set | timeout | 0 | And user "participant2" sees the following messages in room "LOCAL::room" with 200 | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | - | room | users | participant2 | participant2-displayname | Message deleted by author | {"actor":{"type":"user","id":"participant2","name":"participant2@localhost:8180","server":"http:\/\/localhost:8180"}} | Message deleted by author | - | room | federated_users | participant1@{$BASE_URL} | participant1-displayname | Message deleted by author | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"}} | | + | room | users | participant2 | participant2-displayname | Message deleted by you | {"actor":{"type":"user","id":"participant2","name":"participant2-displayname"}} | Message deleted by author | + | room | federated_users | participant1@{$BASE_URL} | participant1-displayname | Message deleted by author | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname","server":"{$BASE_URL}"}} | | Scenario: Error handling of chatting (posting a too long message) Given the following "spreed" app config is set