diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index 7e17b26e2d3..277940b7678 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -131,8 +131,11 @@ public function getPeersForCall(): DataResponse { #[RequireModeratorParticipant] #[Http\Attribute\NoCSRFRequired] public function downloadParticipantsForCall(string $format = 'csv'): DataDownloadResponse|Response { - $timeout = $this->timeFactory->getTime() - Session::SESSION_TIMEOUT; - $participants = $this->participantService->getParticipantsInCall($this->room, $timeout); + $callStart = $this->room->getActiveSince()?->getTimestamp() ?? 0; + if ($callStart === 0) { + return new Response(Http::STATUS_BAD_REQUEST); + } + $participants = $this->participantService->getParticipantsJoinedCurrentCall($this->room, $callStart); if (empty($participants)) { return new Response(Http::STATUS_BAD_REQUEST); @@ -151,12 +154,24 @@ public function downloadParticipantsForCall(string $format = 'csv'): DataDownloa $output = fopen('php://memory', 'w'); fputcsv($output, [ 'name', + 'email', 'type', 'identifier', ]); foreach ($participants as $participant) { - fputcsv($output, [$participant->getAttendee()->getDisplayName(), $participant->getAttendee()->getActorType(), $participant->getAttendee()->getActorId()]); + $email = ''; + if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_EMAILS) { + $email = $participant->getAttendee()->getInvitedCloudId(); + } elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) { + $email = $this->userManager->get($participant->getAttendee()->getActorId())?->getEMailAddress() ?? ''; + } + fputcsv($output, [ + $participant->getAttendee()->getDisplayName(), + $email, + $participant->getAttendee()->getActorType(), + $participant->getAttendee()->getActorId(), + ]); } fseek($output, 0); diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 4535031b049..c6741923a2e 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -1594,6 +1594,22 @@ public function getParticipantsInCall(Room $room, int $maxAge = 0): array { return $this->getParticipantsFromQuery($query, $room); } + /** + * @return Participant[] + */ + public function getParticipantsJoinedCurrentCall(Room $room, int $maxAge): array { + $query = $this->connection->getQueryBuilder(); + + $helper = new SelectHelper(); + $helper->selectAttendeesTable($query); + $query->from('talk_attendees', 'a') + ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->gte('a.last_joined_call', $query->createNamedParameter($maxAge, IQueryBuilder::PARAM_INT))) + ->orderBy('a.id', 'ASC'); + + return $this->getParticipantsFromQuery($query, $room); + } + /** * @param Room $room * @param int $notificationLevel diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 3b2034c10b0..4d8e4899b7c 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -2265,8 +2265,8 @@ public function userDownloadsPeersInCall(string $user, string $identifier, strin $expected = []; foreach ($tableNode->getRows() as $row) { - if ($row[1] === 'guests') { - $row[2] = self::$sessionNameToActorId[$row[2]]; + if ($row[2] === 'guests') { + $row[3] = self::$sessionNameToActorId[$row[3]]; } $expected[] = implode(',', $row); } diff --git a/tests/integration/features/callapi/public.feature b/tests/integration/features/callapi/public.feature index de88c15c985..1e09dba5c4c 100644 --- a/tests/integration/features/callapi/public.feature +++ b/tests/integration/features/callapi/public.feature @@ -95,12 +95,18 @@ Feature: callapi/public And user "guest" joins call "room" with 200 (v4) Then user "participant1" sees 2 peers in call "room" with 200 (v4) And user "guest" sees 2 peers in call "room" with 200 (v4) + And invoking occ with "user:setting participant1 settings email participant1@example.tld" And user "participant2" downloads call participants from "room" as "csv" with 403 (v4) And user "participant1" downloads call participants from "room" as "csv" with 200 (v4) - | name | type | identifier | - | participant1-displayname | users | participant1 | - | | guests | guest1 | + | name | email | type | identifier | + | participant1-displayname | participant1@example.tld | users | participant1 | + | | | guests | guest1 | Then user "guest" leaves call "room" with 200 (v4) + And user "participant1" downloads call participants from "room" as "csv" with 200 (v4) + | name | email | type | identifier | + | participant1-displayname | participant1@example.tld | users | participant1 | + | | | guests | guest1 | + And invoking occ with "user:setting participant1 settings email --delete" Then user "participant1" sees 1 peers in call "room" with 200 (v4) And user "guest" sees 1 peers in call "room" with 200 (v4) Then user "guest" leaves room "room" with 200 (v4)