diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 1f7d9f22152..4c528120ff5 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -2582,12 +2582,26 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse try { $entity = $this->phoneService->getAccountToCallForPhoneNumber($phoneNumber); } catch (DoesNotExistException) { - $this->logger->info('No account found for direct dial-in with number: ' . $phoneNumber); - return new DataResponse(null, Http::STATUS_NOT_FOUND); + $dialoutPrefix = $this->appConfig->getAppValueString('sip_bridge_dialout_prefix', '+'); + + if ($dialoutPrefix === '') { + $this->logger->info('No account found for direct dial-in with number: ' . $phoneNumber); + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + + try { + // Try to find the number with added dialout prefix as a fallback for old sip-bridges + // TODO: Log as error in 26, remove fallback and dialout prefix with 27 + $entity = $this->phoneService->getAccountToCallForPhoneNumber($dialoutPrefix . $phoneNumber); + } catch (DoesNotExistException) { + $this->logger->info('No account found for direct dial-in with number: ' . $phoneNumber); + return new DataResponse(null, Http::STATUS_NOT_FOUND); + } + + $this->logger->warning('Found account for direct dial-in only by adding the dial-out prefix. Please adjust the mapping for number: ' . $phoneNumber); } $caller = trim($caller); - // TODO: Use later and get name from addressbook? $cleanedCaller = $this->phoneNumberUtil->convertToStandardFormat($caller); $user = $this->userManager->get($entity->getActorId()); try { $room = $this->roomService->createConversation( @@ -2603,7 +2617,14 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse return new DataResponse(null, Http::STATUS_INTERNAL_SERVER_ERROR); } - $participant = $this->participantService->joinRoomAsNewGuest($this->roomService, $room, '', true, displayName: $caller); + $participant = $this->participantService->joinRoomAsNewGuest( + $this->roomService, + $room, + '', + true, + displayName: $caller, + phoneNumber: $caller, + ); return new DataResponse($this->formatRoom($room, $participant)); } diff --git a/lib/Migration/Version25000Date20260918142246.php b/lib/Migration/Version25000Date20260918142246.php new file mode 100644 index 00000000000..d364dbbefce --- /dev/null +++ b/lib/Migration/Version25000Date20260918142246.php @@ -0,0 +1,55 @@ +appConfig->getAppValueString('sip_bridge_dialout_prefix', '+'); + + if ($dialoutPrefix === '') { + return; + } + + $update = $this->connection->getQueryBuilder(); + $update->update('talk_phone_numbers') + ->set('phone_number', $update->func()->concat( + $update->createNamedParameter($dialoutPrefix, IQueryBuilder::PARAM_STR), + 'phone_number', + )) + ->where($update->expr()->gte( + $update->func()->charLength('phone_number'), + $update->createNamedParameter(6, IQueryBuilder::PARAM_INT)) + ); + + $update->executeStatement(); + } +} diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 04bd24d149c..47c7c0615bf 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -601,7 +601,7 @@ public function joinRoomAsFederatedUser(Room $room, string $actorType, string $a * @throws InvalidPasswordException * @throws UnauthorizedException */ - public function joinRoomAsNewGuest(RoomService $roomService, Room $room, string $password, bool $passedPasswordProtection = false, ?Participant $previousParticipant = null, ?string $displayName = null): Participant { + public function joinRoomAsNewGuest(RoomService $roomService, Room $room, string $password, bool $passedPasswordProtection = false, ?Participant $previousParticipant = null, ?string $displayName = null, ?string $phoneNumber = null): Participant { $event = new BeforeGuestJoinedRoomEvent($room, $password, $passedPasswordProtection); $this->dispatcher->dispatchTyped($event); @@ -635,6 +635,10 @@ public function joinRoomAsNewGuest(RoomService $roomService, Room $room, string if ($displayName !== null && $displayName !== '') { $attendee->setDisplayName($displayName); } + if ($phoneNumber !== null && $phoneNumber !== '') { + $attendee->setPhoneNumber($phoneNumber); + $attendee->setActorType(Attendee::ACTOR_PHONES); + } $this->attendeeMapper->insert($attendee); diff --git a/lib/Service/PhoneNumberValidation.php b/lib/Service/PhoneNumberValidation.php index c1ce47af600..2f44cbe83d7 100644 --- a/lib/Service/PhoneNumberValidation.php +++ b/lib/Service/PhoneNumberValidation.php @@ -23,9 +23,7 @@ public function __construct( * Validate input as a phone number * * - Local number: allow - * - International number - * a. If valid, strip + and allow - * b. If invalid, throw + * - International number: If invalid, throw * @throws \InvalidArgumentException When the number is invalid */ public function validateNumber(string $phoneNumber): string { @@ -46,10 +44,6 @@ public function validateNumber(string $phoneNumber): string { throw new \InvalidArgumentException(); } - if (str_starts_with($standardPhoneNumber, '+')) { - return substr($standardPhoneNumber, 1); - } - - throw new \InvalidArgumentException(); + return $standardPhoneNumber; } } diff --git a/lib/SetupCheck/SIPConfiguration.php b/lib/SetupCheck/SIPConfiguration.php index 6a0611f88e4..c29b433a77e 100644 --- a/lib/SetupCheck/SIPConfiguration.php +++ b/lib/SetupCheck/SIPConfiguration.php @@ -48,9 +48,11 @@ public function run(): SetupResult { $query->select('phone_number') ->from('talk_phone_numbers') ->where($query->expr()->like('phone_number', $query->createNamedParameter( - $this->connection->escapeLikeParameter('+') . '%' - ))) - ->orWhere($query->expr()->like('phone_number', $query->createNamedParameter( + // TODO: Temporary disabled while we migrate to leading `+` for international numbers + // TODO: Either to be deleted later or should complain for numbers without it + // $this->connection->escapeLikeParameter('+') . '%' + // ))) + // ->orWhere($query->expr()->like('phone_number', $query->createNamedParameter( $this->connection->escapeLikeParameter('0') . '%' )));