From 541d23ade6042f89bc2278e2a83291d91f9594f9 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Wed, 7 Oct 2026 17:16:22 +0200 Subject: [PATCH 1/6] chore(config): refactor sip settings to AppConfig, changes to different similar flags Signed-off-by: Christian Lorang --- docs/settings.md | 2 +- lib/Capabilities.php | 4 +-- lib/Config.php | 28 +++++++---------- lib/ConfigLexicon.php | 6 ++++ lib/Controller/CallController.php | 9 ++++-- lib/Controller/RoomController.php | 30 +++++++++++-------- lib/Controller/SettingsController.php | 11 +++---- lib/Controller/SignalingController.php | 6 ++-- lib/GuestManager.php | 4 ++- lib/Manager.php | 2 +- lib/Service/InvitationService.php | 5 +++- lib/Service/ParticipantService.php | 6 ++-- lib/Service/RoomFormatter.php | 4 +-- lib/Settings/Admin/AdminSettings.php | 14 ++++----- lib/SetupCheck/SIPConfiguration.php | 28 +++++++++++++++-- src/components/AdminSettings/SIPBridge.vue | 2 +- .../features/callapi/sip-dialout.feature | 2 +- .../features/conversation-1/create.feature | 2 +- .../conversation-4/classified.feature | 2 +- .../conversation-5/sip-dialout.feature | 4 +-- tests/php/CapabilitiesTest.php | 2 ++ .../Controller/SignalingControllerTest.php | 13 ++++---- tests/php/GuestManagerTest.php | 5 ++++ tests/php/Service/InvitationServiceTest.php | 13 ++++++-- .../ParticipantServiceParticipantTypeTest.php | 2 ++ tests/php/Service/ParticipantServiceTest.php | 4 +++ 26 files changed, 138 insertions(+), 72 deletions(-) diff --git a/docs/settings.md b/docs/settings.md index dddff1f6dbe..ba3712015f2 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -1,4 +1,4 @@ -# Settings API +# Settings API * Base endpoint: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 19 diff --git a/lib/Capabilities.php b/lib/Capabilities.php index d1b2118ec74..ba7ea5737b6 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -293,8 +293,8 @@ public function getCapabilities(): array { // 'predefined-backgrounds' => list, // 'predefined-backgrounds-v2' => list, 'can-upload-background' => false, - 'sip-enabled' => $this->talkConfig->isSIPConfigured(), - 'sip-dialout-enabled' => $this->talkConfig->isSIPDialOutEnabled(), + 'sip-enabled' => !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)), + 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT), 'default-phone-region' => $this->serverConfig->getSystemValueString('default_phone_region'), 'can-enable-sip' => false, 'start-without-media' => $this->talkConfig->getCallsStartWithoutMedia($user?->getUID()), diff --git a/lib/Config.php b/lib/Config.php index fa2ca1e1026..b621d0ccc08 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -106,6 +106,12 @@ class Config { public const string HOSTED_SIGNALING_SERVER_ACCOUNT = 'hosted_signaling_server_account'; public const string HOSTED_SIGNALING_SERVER_NONCE = 'hosted_signaling_server_nonce'; public const string HOSTED_SIGNALING_SERVER_ACCOUNT_ID = 'hosted_signaling_server_account_id'; + public const string SIP_BRIDGE_DIALIN_INFO = 'sip_bridge_dialin_info'; + public const string SIP_BRIDGE_DIALOUT_ANONYMOUS = 'sip_bridge_dialout_anonymous'; + public const string SIP_BRIDGE_DIALOUT_NUMBER = 'sip_bridge_dialout_number'; + public const string SIP_BRIDGE_DIALOUT_PREFIX = 'sip_bridge_dialout_prefix'; + public const string SIP_BRIDGE_SHARED_SECRET = 'sip_bridge_shared_secret'; + public const string SIP_BRIDGE_DIALOUT = 'sip_bridge_dialout'; /** * 1. Call recording, … @@ -177,8 +183,8 @@ public function getSIPGroups(): array { } public function isSIPConfigured(): bool { - return $this->getSIPSharedSecret() !== '' - && $this->getDialInInfo() !== ''; + return $this->appConfig->getAppValueString(self::SIP_BRIDGE_SHARED_SECRET) !== '' + && $this->appConfig->getAppValueString(self::SIP_BRIDGE_DIALIN_INFO) !== ''; } /** @@ -204,15 +210,7 @@ public function isBreakoutRoomsEnabled(): bool { } public function isConversationSubfoldersEnabled(): bool { - return $this->appConfig->getAppValueBool(self::CONVERSATION_SUBFOLDERS, true); - } - - public function getDialInInfo(): string { - return $this->config->getAppValue('spreed', 'sip_bridge_dialin_info'); - } - - public function getSIPSharedSecret(): string { - return $this->config->getAppValue('spreed', 'sip_bridge_shared_secret'); + return $this->appConfig->getAppValueBool(self::CONVERSATION_SUBFOLDERS); } public function canUserEnableSIP(IUser $user): bool { @@ -222,7 +220,7 @@ public function canUserEnableSIP(IUser $user): bool { $this->canEnableSIP[$user->getUID()] = false; - $allowedGroups = $this->getSIPGroups(); + $allowedGroups = $this->appConfig->getAppValueArray(self::ALLOWED_GROUPS_SIP); if (empty($allowedGroups)) { $this->canEnableSIP[$user->getUID()] = true; } else { @@ -234,17 +232,13 @@ public function canUserEnableSIP(IUser $user): bool { } public function canUserDialOutSIP(IUser $user): bool { - if (!$this->isSIPDialOutEnabled()) { + if (!(!empty($this->appConfig->getAppValueString(self::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(self::SIP_BRIDGE_SHARED_SECRET)))) { return false; } return $this->canUserEnableSIP($user); } - public function isSIPDialOutEnabled(): bool { - return $this->config->getAppValue('spreed', 'sip_dialout', 'no') !== 'no'; - } - public function getRecordingServers(): array { $recording = $this->appConfig->getAppValueArray(self::RECORDING_SERVERS); return $recording['servers'] ?? []; diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php index 9b0094d151d..a01a85740f4 100644 --- a/lib/ConfigLexicon.php +++ b/lib/ConfigLexicon.php @@ -214,6 +214,12 @@ public function getAppConfigs(): array { new Entry(Config::HOSTED_SIGNALING_SERVER_ACCOUNT, ValueType::ARRAY, [], definition: 'Account information of the hosted signaling server', flags: IAppConfig::FLAG_SENSITIVE, rename: 'hosted-signaling-server-account'), new Entry(Config::HOSTED_SIGNALING_SERVER_NONCE, ValueType::STRING, '', definition: 'Temporary nonce while configuring the hosted signaling server', flags: IAppConfig::FLAG_SENSITIVE, rename: 'hosted-signaling-server-nonce'), new Entry(Config::HOSTED_SIGNALING_SERVER_ACCOUNT_ID, ValueType::STRING, '', definition: 'Account identifier of the hosted signaling server', flags: IAppConfig::FLAG_SENSITIVE, rename: 'hosted-signaling-server-account-id'), + new Entry(Config::SIP_BRIDGE_DIALIN_INFO, ValueType::STRING, '', definition: 'Additional information added in the SIP dial-in invitation mail and sidebar', flags: IAppConfig::FLAG_SENSITIVE), + new Entry(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS, ValueType::BOOL, false, definition: 'When set to true, all out-going SIP calls will be anonymous calls (CLIR)'), + new Entry(Config::SIP_BRIDGE_DIALOUT_NUMBER, ValueType::STRING, '', definition: 'Fallback phone number that is used as caller for out-going calls when the user has no phone-number configured (has to be E164 `+49123456789` formatted'), + new Entry(Config::SIP_BRIDGE_DIALOUT_PREFIX, ValueType::STRING, '+', definition: 'Prefix stat is added before the first configured phone-number of a user to make it a valid E164 number to be used as a caller for out-going calls'), + new Entry(Config::SIP_BRIDGE_SHARED_SECRET, ValueType::STRING, '', definition: 'Shared secret allowing the SIP bridge to authenticate on the Nextcloud server', flags: IAppConfig::FLAG_SENSITIVE), + new Entry(Config::SIP_BRIDGE_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured', rename: 'sip_dialout'), ]; } diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index 0935ca32055..c49907ee123 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -461,10 +461,10 @@ public function sipDialOut(int $attendeeId): DataResponse { } $callerNumber = true; - if ($this->appConfig->getAppValueBool('sip_bridge_dialout_anonymous')) { + if ($this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS)) { $callerNumber = false; - } elseif ($this->appConfig->getAppValueString('sip_bridge_dialout_number') !== '') { - $callerNumber = $this->appConfig->getAppValueString('sip_bridge_dialout_number'); + } elseif ($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_NUMBER) !== '') { + $callerNumber = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_NUMBER); } // No elseif, so we have the fallback to sip_bridge_dialout_number when the caller is no user or doesn't have a number @@ -474,6 +474,9 @@ public function sipDialOut(int $attendeeId): DataResponse { $numbers = $this->phoneNumberMapper->findByUser($attendee->getActorId()); if (!empty($numbers)) { $callerNumber = array_shift($numbers)->getPhoneNumber(); + $number = array_shift($numbers); + $callerNumber = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_PREFIX); + $callerNumber .= $number->getPhoneNumber(); } } } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 2b863e433fa..413d0360093 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -208,9 +208,9 @@ protected function getTalkHashHeader(): array { $this->config->getAppValue('spreed', 'federation_enabled'), json_encode($this->appConfig->getAppValueArray(Config::ALLOWED_GROUPS_SIP)), $this->appConfig->getAppValueBool(Config::MATTERBRIDGE_ENABLED), - $this->config->getAppValue('spreed', 'sip_bridge_dialin_info'), - $this->config->getAppValue('spreed', 'sip_bridge_shared_secret'), $this->appConfig->getAppValueInt(Config::RECORDING_CONSENT), + $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO), + $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET), $this->appConfig->getAppValueBool(Config::CALL_RECORDING_TRANSCRIPTION), $this->appConfig->getAppValueBool(Config::CALL_RECORDING_SUMMARY), $this->config->getAppValue('theming', 'cachebuster', '1'), @@ -588,7 +588,7 @@ public function getNoteToSelfConversation(): DataResponse { private function validateSIPBridgeRequest(string $token): bool { $random = $this->request->getHeader('talk-sipbridge-random'); $checksum = $this->request->getHeader('talk-sipbridge-checksum'); - $secret = $this->talkConfig->getSIPSharedSecret(); + $secret = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET); return $this->checksumVerificationService->validateRequest($random, $checksum, $secret, $token); } @@ -834,6 +834,7 @@ public function createRoom( } $isClassified = $preset === Classified::getIdentifier(); + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); // Enabling SIP dial-in is restricted to the configured groups, so requesting // it at creation time requires the same permission as toggling it later on. @@ -843,8 +844,7 @@ public function createRoom( $sipEnabled = Webinary::SIP_DISABLED; } elseif ($sipEnabled !== Webinary::SIP_DISABLED && $this->forcedParameters->getForcedParameter(Parameter::SIP_ENABLED) === null - && (!$this->talkConfig->isSIPConfigured() - || !$this->talkConfig->canUserEnableSIP($user))) { + && (!$isSIPConfigured || !$this->talkConfig->canUserEnableSIP($user))) { if ($sipEnabled === $this->defaultParameters->getParameters()[Parameter::SIP_ENABLED->value]) { // Clients send the administrator configured default value also when the // user did not request SIP themselves, so it is silently disabled instead. @@ -1432,7 +1432,7 @@ protected function formatParticipantList(array $participants, bool $includeStatu 'phoneNumber' => '', 'callId' => '', ]; - if ($this->talkConfig->isSIPConfigured() + if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) && $this->room->getSIPEnabled() !== Webinary::SIP_DISABLED && ($this->participant->hasModeratorPermissions(false) || $this->participant->getAttendee()->getId() === $participant->getAttendee()->getId())) { @@ -1512,7 +1512,7 @@ protected function formatParticipantList(array $participants, bool $includeStatu $result['displayName'] = $participant->getAttendee()->getDisplayName(); } elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_PHONES) { $result['displayName'] = $participant->getAttendee()->getDisplayName(); - if ($this->talkConfig->isSIPConfigured() + if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) && $this->participant->hasModeratorPermissions(false)) { $result['phoneNumber'] = $participant->getAttendee()->getPhoneNumber(); @@ -1681,9 +1681,10 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u return new DataResponse(['error' => 'classified'], Http::STATUS_BAD_REQUEST); } + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); if ( !$addedBy instanceof IUser - || !$this->talkConfig->isSIPConfigured() + || !$isSIPConfigured || !$this->talkConfig->canUserDialOutSIP($addedBy) || preg_match(Room::SIP_INCOMPATIBLE_REGEX, $this->room->getToken()) || ($this->room->getType() !== Room::TYPE_GROUP && $this->room->getType() !== Room::TYPE_PUBLIC)) { @@ -2604,6 +2605,7 @@ public function joinFederatedRoom(string $token, ?string $sessionId): DataRespon 'apiVersion' => '(v4)', 'token' => '[a-z0-9]{4,30}', ])] + public function verifyDialInPin(#[SensitiveParameter] string $pin): DataResponse { if (!$this->talkConfig->isSIPConfigured()) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); @@ -2654,7 +2656,8 @@ public function verifyDialInPin(#[SensitiveParameter] string $pin): DataResponse 'apiVersion' => '(v4)', ])] public function directDialIn(string $phoneNumber, string $caller): DataResponse { - if (!$this->talkConfig->isSIPConfigured()) { + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + if (!$isSIPConfigured) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2743,7 +2746,8 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse 'token' => '[a-z0-9]{4,30}', ])] public function verifyDialOutNumber(string $number, array $options = []): DataResponse { - if (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->isSIPDialOutEnabled()) { + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + if (!$isSIPConfigured) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2841,7 +2845,8 @@ public function createGuestByDialIn(): DataResponse { 'token' => '[a-z0-9]{4,30}', ])] public function rejectedDialOutRequest(string $callId, array $options = []): DataResponse { - if (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->isSIPDialOutEnabled()) { + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + if (!$isSIPConfigured) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -3312,7 +3317,8 @@ public function setSIPEnabled(int $state): DataResponse { return new DataResponse(['error' => 'config'], Http::STATUS_FORBIDDEN); } - if (!$this->talkConfig->isSIPConfigured()) { + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + if (!$isSIPConfigured) { return new DataResponse(['error' => 'config'], Http::STATUS_PRECONDITION_FAILED); } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 4df2678b84c..22c48fe55bc 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -17,6 +17,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\EventDispatcher\IEventDispatcher; +use OCP\AppFramework\Services\IAppConfig; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; @@ -30,6 +31,7 @@ public function __construct( string $appName, IRequest $request, private readonly IConfig $config, + private readonly IAppConfig $appConfig, private readonly IGroupManager $groupManager, private readonly BeforePreferenceSetEventListener $preferenceListener, private readonly ?string $userId, @@ -89,11 +91,10 @@ public function setSIPSettings( } } - $sharedSecretChanged = $this->config->getAppValue('spreed', 'sip_bridge_shared_secret') !== $sharedSecret; - - $this->config->setAppValue('spreed', 'sip_bridge_groups', json_encode($groups)); - $this->config->setAppValue('spreed', 'sip_bridge_dialin_info', $dialInInfo); - $this->config->setAppValue('spreed', 'sip_bridge_shared_secret', $sharedSecret); + $sharedSecretChanged = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET) !== $sharedSecret; + $this->appConfig->setAppValueArray(Config::ALLOWED_GROUPS_SIP, $groups); + $this->appConfig->setAppValueString(Config::SIP_BRIDGE_DIALIN_INFO, $dialInInfo); + $this->appConfig->setAppValueString(Config::SIP_BRIDGE_SHARED_SECRET, $sharedSecret); $this->dispatcher->dispatchTyped(new CriticalActionPerformedEvent( 'SIP bridge settings were changed: groups "{sipGroups}", shared secret {sharedSecret}', diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php index 9bddc815a13..c5ab4ccbf91 100644 --- a/lib/Controller/SignalingController.php +++ b/lib/Controller/SignalingController.php @@ -37,6 +37,7 @@ use OCP\AppFramework\Http\Attribute\RequestHeader; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\DB\Exception; use OCP\EventDispatcher\IEventDispatcher; @@ -60,6 +61,7 @@ public function __construct( string $appName, IRequest $request, private readonly Config $talkConfig, + private readonly IAppConfig $appConfig, private readonly \OCA\Talk\Signaling\Manager $signalingManager, private readonly ISession $serverSession, private readonly TalkSession $session, @@ -119,7 +121,7 @@ private function validateRecordingBackendRequest(string $data): bool { private function validateSIPBridgeRequest(string $data): bool { $random = $this->request->getHeader('talk-sipbridge-random'); $checksum = $this->request->getHeader('talk-sipbridge-checksum'); - $secret = $this->talkConfig->getSIPSharedSecret(); + $secret = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET); try { return $this->checksumVerificationService->validateRequest($random, $checksum, $secret, $data); } catch (UnauthorizedException) { @@ -269,7 +271,7 @@ public function getSettings(string $token = ''): DataResponse { 'federation' => $this->getFederationSettings($room), 'stunservers' => $stun, 'turnservers' => $turn, - 'sipDialinInfo' => $this->talkConfig->isSIPConfigured() ? $this->talkConfig->getDialInInfo() : '', + 'sipDialinInfo' => !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) ? $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO) : '', ]; if ($signalingMode !== Config::SIGNALING_INTERNAL) { diff --git a/lib/GuestManager.php b/lib/GuestManager.php index bf8c41d1afc..4d186f40a91 100644 --- a/lib/GuestManager.php +++ b/lib/GuestManager.php @@ -20,6 +20,7 @@ use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\PollService; use OCA\Talk\Service\RoomService; +use OCP\AppFramework\Services\IAppConfig; use OCP\Defaults; use OCP\EventDispatcher\IEventDispatcher; use OCP\IDateTimeZone; @@ -35,6 +36,7 @@ class GuestManager { public function __construct( private readonly Config $talkConfig, + private readonly IAppConfig $appConfig, private readonly IEmailValidator $emailValidator, private readonly IMailer $mailer, private readonly Defaults $defaults, @@ -284,7 +286,7 @@ public function sendEmailInvitation(Room $room, Participant $participant): void $template->addBodyText($this->l->t('You can also dial-in via phone with the following details')); $template->addBodyListItem( - $this->talkConfig->getDialInInfo(), + $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO), $this->l->t('Dial-in information'), $this->url->getAbsoluteURL($this->url->imagePath('spreed', 'phone.png')) ); diff --git a/lib/Manager.php b/lib/Manager.php index 5f681662c75..aa135dc30b1 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -1461,7 +1461,7 @@ protected function getRoomNameByParticipants(Room $room): string { */ protected function getNewToken(): string { $entropy = max(8, $this->appConfig->getAppValueInt(Config::TOKEN_ENTROPY)); // For update cases - $digitsOnly = $this->talkConfig->isSIPConfigured(); + $digitsOnly = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); if ($digitsOnly) { // Increase default token length as we only use numbers $entropy = max(10, $entropy); diff --git a/lib/Service/InvitationService.php b/lib/Service/InvitationService.php index 9f6d41a59b0..b1594b3621d 100644 --- a/lib/Service/InvitationService.php +++ b/lib/Service/InvitationService.php @@ -15,6 +15,7 @@ use OCA\Talk\Model\InvitationList; use OCA\Talk\Room; use OCP\App\IAppManager; +use OCP\AppFramework\Services\IAppConfig; use OCP\Federation\ICloudIdManager; use OCP\IConfig; use OCP\IGroup; @@ -35,6 +36,7 @@ public function __construct( private readonly ParticipantService $participantService, private readonly IConfig $serverConfig, private readonly Config $talkConfig, + private readonly IAppConfig $appConfig, private readonly IEmailValidator $emailValidator, ) { } @@ -192,7 +194,8 @@ protected function validatePhoneInvitations(InvitationList $invitationList, arra return; } - if (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->canUserDialOutSIP($currentUser)) { + $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + if (!$isSIPConfigured || !$this->talkConfig->canUserDialOutSIP($currentUser)) { $invitationList->setPhoneNumberResults([], $phoneNumbers); return; } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 1b767321f85..22ab1491cfe 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -64,6 +64,7 @@ use OCA\Talk\Webinary; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Comments\IComment; use OCP\DB\Exception; @@ -121,6 +122,7 @@ class ParticipantService { public function __construct( private readonly Config $talkConfig, + private readonly IAppConfig $appConfig, private readonly AttendeeMapper $attendeeMapper, private readonly SessionMapper $sessionMapper, private readonly SessionService $sessionService, @@ -1169,7 +1171,7 @@ public function inviteEmailAddress(Room $room, string $actorId, string $email, ? } if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED - && $this->talkConfig->isSIPConfigured()) { + && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET))) { $attendee->setPin($this->generatePin()); } @@ -1188,7 +1190,7 @@ public function inviteEmailAddress(Room $room, string $actorId, string $email, ? public function generatePinForParticipant(Room $room, Participant $participant): void { $attendee = $participant->getAttendee(); if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED - && $this->talkConfig->isSIPConfigured() + && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) && ($attendee->getActorType() === Attendee::ACTOR_USERS || $attendee->getActorType() === Attendee::ACTOR_EMAILS) && !$attendee->getPin()) { $attendee->setPin($this->generatePin()); diff --git a/lib/Service/RoomFormatter.php b/lib/Service/RoomFormatter.php index 0498e3cdd25..f1f67b504c7 100644 --- a/lib/Service/RoomFormatter.php +++ b/lib/Service/RoomFormatter.php @@ -269,7 +269,7 @@ public function formatRoomV4( } } - if ($this->talkConfig->isSIPConfigured()) { + if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET))) { $roomData['sipEnabled'] = $room->getSIPEnabled(); if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED) { // Generate a PIN if the attendee is a user and doesn't have one. @@ -351,7 +351,7 @@ public function formatRoomV4( } $roomData['canEnableSIP'] - = $this->talkConfig->isSIPConfigured() + = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) && !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken()) && ($room->getType() === Room::TYPE_GROUP || $room->getType() === Room::TYPE_PUBLIC) && $currentParticipant->hasModeratorPermissions(false) diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php index cf1bb542d9b..86afd759667 100644 --- a/lib/Settings/Admin/AdminSettings.php +++ b/lib/Settings/Admin/AdminSettings.php @@ -461,15 +461,15 @@ protected function initRecording(): void { } protected function initSIPBridge(): void { - $groups = $this->getGroupDetailsArray($this->talkConfig->getSIPGroups(), 'sip_bridge_groups'); + $groups = $this->getGroupDetailsArray($this->appConfig->getAppValueArray(Config::ALLOWED_GROUPS_SIP), Config::ALLOWED_GROUPS_SIP); $this->initialState->provideInitialState('sip_bridge_groups', $groups); - $this->initialState->provideInitialState('sip_bridge_shared_secret', $this->talkConfig->getSIPSharedSecret()); - $this->initialState->provideInitialState('sip_bridge_dialin_info', $this->talkConfig->getDialInInfo()); - $this->initialState->provideInitialState('sip_bridge_dialout', $this->talkConfig->isSIPDialOutEnabled()); - $this->initialState->provideInitialState('sip_bridge_dialout_anonymous', $this->appConfig->getAppValueBool('sip_bridge_dialout_anonymous')); - $this->initialState->provideInitialState('sip_bridge_dialout_number', $this->serverConfig->getAppValue('spreed', 'sip_bridge_dialout_number', '')); - $this->initialState->provideInitialState('sip_bridge_dialout_prefix', $this->serverConfig->getAppValue('spreed', 'sip_bridge_dialout_prefix', '+')); + $this->initialState->provideInitialState('sip_bridge_shared_secret', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + $this->initialState->provideInitialState('sip_bridge_dialin_info', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)); + $this->initialState->provideInitialState('sip_bridge_dialout', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)); + $this->initialState->provideInitialState('sip_bridge_dialout_anonymous', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS)); + $this->initialState->provideInitialState('sip_bridge_dialout_number', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_NUMBER)); + $this->initialState->provideInitialState('sip_bridge_dialout_prefix', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_PREFIX)); } protected function getGroupDetailsArray(array $gids, string $configKey): array { diff --git a/lib/SetupCheck/SIPConfiguration.php b/lib/SetupCheck/SIPConfiguration.php index 21a06c460a5..2597e43f48c 100644 --- a/lib/SetupCheck/SIPConfiguration.php +++ b/lib/SetupCheck/SIPConfiguration.php @@ -42,8 +42,32 @@ public function run(): SetupResult { return SetupResult::success($this->l->t('Using the SIP functionality requires a High-performance backend.')); } - if ($this->talkConfig->getSIPSharedSecret() === '' - && $this->talkConfig->getDialInInfo() === '' + $query = $this->connection->getQueryBuilder(); + $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( + $this->connection->escapeLikeParameter('0') . '%' + ))); + + $result = $query->executeQuery(); + $invalidNumbers = $result->fetchFirstColumn(); + $result->closeCursor(); + + if (!empty($invalidNumbers)) { + $message = $this->l->t("Assigned Talk phone numbers must not start with + or 0. Please remove or update the following numbers:\n{list}"); + $message = str_replace( + '{list}', + implode("\n", $invalidNumbers), + $message + ); + return SetupResult::error($message, 'https://portal.nextcloud.com/article/Nextcloud-Talk/Nextcloud-Talk-Phone/Direct-Dial-in#content-provisioning'); + } + + if ($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET) === '' + && $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO) === '' && $this->appConfig->getAppValueInt(Config::FEATURE_HINTS_HIDDEN) < 34) { return SetupResult::info($this->l->t('No SIP backend configured')); } diff --git a/src/components/AdminSettings/SIPBridge.vue b/src/components/AdminSettings/SIPBridge.vue index 2fa0dcb5fe6..7997c6d0966 100644 --- a/src/components/AdminSettings/SIPBridge.vue +++ b/src/components/AdminSettings/SIPBridge.vue @@ -266,7 +266,7 @@ export default { dialInInfo: this.dialInInfo, }) if (this.currentSetup.dialOutEnabled !== this.dialOutEnabled) { - await OCP.AppConfig.setValue('spreed', 'sip_dialout', this.dialOutEnabled ? 'yes' : 'no') + await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout', this.dialOutEnabled) } if (this.currentSetup.dialOutAnonymous !== this.dialOutAnonymous) { await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout_anonymous', String(this.dialOutAnonymous)) diff --git a/tests/integration/features/callapi/sip-dialout.feature b/tests/integration/features/callapi/sip-dialout.feature index 800cf2023b5..d17bef25290 100644 --- a/tests/integration/features/callapi/sip-dialout.feature +++ b/tests/integration/features/callapi/sip-dialout.feature @@ -11,7 +11,7 @@ Feature: callapi/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | yes | + | sip_bridge_dialout | true | And user "participant1" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/integration/features/conversation-1/create.feature b/tests/integration/features/conversation-1/create.feature index ba53224c2ae..eb0305d0db8 100644 --- a/tests/integration/features/conversation-1/create.feature +++ b/tests/integration/features/conversation-1/create.feature @@ -99,7 +99,7 @@ Feature: conversation-1/create | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | default_sip_enabled | 1 | + | sip_bridge_dialout | true | # The default value is sent by clients without the user requesting SIP, # so it is disabled instead of failing the creation When user "participant1" creates room "room" (v4) diff --git a/tests/integration/features/conversation-4/classified.feature b/tests/integration/features/conversation-4/classified.feature index 4e6076c6c8d..f6fac3c5bb7 100644 --- a/tests/integration/features/conversation-4/classified.feature +++ b/tests/integration/features/conversation-4/classified.feature @@ -155,7 +155,7 @@ Feature: conversation-4/classified | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | yes | + | sip_bridge_dialout | true | And user "participant1" creates room "classified" (v4) | roomType | 2 | | roomName | classified | diff --git a/tests/integration/features/conversation-5/sip-dialout.feature b/tests/integration/features/conversation-5/sip-dialout.feature index bd8f97ad96c..f28cdbc3d79 100644 --- a/tests/integration/features/conversation-5/sip-dialout.feature +++ b/tests/integration/features/conversation-5/sip-dialout.feature @@ -10,7 +10,7 @@ Feature: conversation-5/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | yes | + | sip_dialout | true | Given user "participant1" creates room "room" (v4) | roomType | 3 | | roomName | room | @@ -31,7 +31,7 @@ Feature: conversation-5/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | yes | + | sip_bridge_dialout | true | Given user "participant2" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php index 768025f9d58..560e1dfeb31 100644 --- a/tests/php/CapabilitiesTest.php +++ b/tests/php/CapabilitiesTest.php @@ -381,6 +381,8 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea ->willReturnMap([ ['backgrounds_default_for_users', true, true], ['backgrounds_upload_users', true, true], + ['sip_bridge_dialout', false], + ['sip_bridge_dialout_anonymous', false], ]); $this->appConfig->expects($this->any())->method('getAppValueInt') diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index 773ecd4cd1d..62731a6622e 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -138,6 +138,7 @@ private function recreateSignalingController() { 'spreed', $this->request, $this->config, + $this->appConfig, $this->signalingManager, $this->serverSession, $this->session, @@ -1375,7 +1376,7 @@ public function testLeaveRoomWithOldSession(): void { $dbConnection, \OCP\Server::get(IConfig::class), $this->createMock(Config::class), - $this->appConfig, + $this->createMock(IAppConfig::class), \OCP\Server::get(IAppManager::class), \OCP\Server::get(AttendeeMapper::class), \OCP\Server::get(SessionMapper::class), @@ -1461,8 +1462,8 @@ private function sipBridgeChecksum(string $data, string $random): string { } private function setUpSIPBridgeConfig(): void { - $this->config = $this->createMock(Config::class); - $this->config->method('getSIPSharedSecret')->willReturn(self::SIP_BRIDGE_SECRET); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)->willReturn(self::SIP_BRIDGE_SECRET); $this->userId = null; $this->recreateSignalingController(); } @@ -1510,12 +1511,14 @@ public function testGetSettingsSIPBridgeShortRandom(): void { public function testGetSettingsSIPBridgeValidNoToken(): void { $this->config = $this->createMock(Config::class); - $this->config->method('getSIPSharedSecret')->willReturn(self::SIP_BRIDGE_SECRET); + $this->appConfig = $this->createMock(IAppConfig::class); + $this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)->willReturn(self::SIP_BRIDGE_SECRET); $this->config->method('getStunServers')->willReturn([]); $this->config->method('getTurnSettings')->willReturn([]); $this->config->method('getSignalingMode')->willReturn(Config::SIGNALING_INTERNAL); $this->config->method('getHideSignalingWarning')->willReturn(false); - $this->config->method('isSIPConfigured')->willReturn(false); + $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); + $this->assertFalse($isSIPConfigured); $this->userId = null; $this->recreateSignalingController(); diff --git a/tests/php/GuestManagerTest.php b/tests/php/GuestManagerTest.php index e708e2ef3ac..213897e31aa 100644 --- a/tests/php/GuestManagerTest.php +++ b/tests/php/GuestManagerTest.php @@ -17,6 +17,7 @@ use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\PollService; use OCA\Talk\Service\RoomService; +use OCP\AppFramework\Services\IAppConfig; use OCP\Defaults; use OCP\EventDispatcher\IEventDispatcher; use OCP\IDateTimeZone; @@ -32,6 +33,7 @@ class GuestManagerTest extends TestCase { protected Config&MockObject $talkConfig; + protected IAppConfig&MockObject $appConfig; protected IEmailValidator&MockObject $emailValidator; protected IMailer&MockObject $mailer; protected Defaults&MockObject $defaults; @@ -48,6 +50,7 @@ class GuestManagerTest extends TestCase { public function setUp(): void { parent::setUp(); $this->talkConfig = $this->createMock(Config::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->emailValidator = $this->createMock(IEmailValidator::class); $this->mailer = $this->createMock(IMailer::class); $this->defaults = $this->createMock(Defaults::class); @@ -67,6 +70,7 @@ public function getGuestManager(array $methods = []): GuestManager|MockObject { return $this->getMockBuilder(GuestManager::class) ->setConstructorArgs([ $this->talkConfig, + $this->appConfig, $this->emailValidator, $this->mailer, $this->defaults, @@ -86,6 +90,7 @@ public function getGuestManager(array $methods = []): GuestManager|MockObject { return new GuestManager( $this->talkConfig, + $this->appConfig, $this->emailValidator, $this->mailer, $this->defaults, diff --git a/tests/php/Service/InvitationServiceTest.php b/tests/php/Service/InvitationServiceTest.php index 631e8484c7d..7656ee07a30 100644 --- a/tests/php/Service/InvitationServiceTest.php +++ b/tests/php/Service/InvitationServiceTest.php @@ -14,6 +14,7 @@ use OCA\Talk\Service\InvitationService; use OCA\Talk\Service\ParticipantService; use OCP\App\IAppManager; +use OCP\AppFramework\Services\IAppConfig; use OCP\Federation\ICloudId; use OCP\Federation\ICloudIdManager; use OCP\IConfig; @@ -35,6 +36,7 @@ class InvitationServiceTest extends TestCase { protected ParticipantService&MockObject $participantService; protected IConfig&MockObject $serverConfig; protected Config&MockObject $talkConfig; + protected IAppConfig&MockObject $appConfig; protected IEmailValidator&MockObject $emailValidator; protected InvitationService $service; @@ -50,6 +52,7 @@ public function setUp(): void { $this->participantService = $this->createMock(ParticipantService::class); $this->serverConfig = $this->createMock(IConfig::class); $this->talkConfig = $this->createMock(Config::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->emailValidator = $this->createMock(IEmailValidator::class); $this->service = new InvitationService( @@ -62,6 +65,7 @@ public function setUp(): void { $this->participantService, $this->serverConfig, $this->talkConfig, + $this->appConfig, $this->emailValidator, ); } @@ -69,7 +73,8 @@ public function setUp(): void { public function testPhoneInvitationsAreRejectedWhenCreatingClassifiedConversation(): void { $currentUser = $this->createStub(IUser::class); // SIP is fully available, only the classified flag must reject the number - $this->talkConfig->method('isSIPConfigured')->willReturn(true); + $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); + $this->assertTrue($isSIPConfigured); $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->phoneNumberUtil->expects(self::never()) ->method('convertToStandardFormat'); @@ -89,7 +94,8 @@ public function testPhoneInvitationsAreRejectedForClassifiedRoom(): void { $currentUser = $this->createStub(IUser::class); $room = $this->createMock(Room::class); $room->method('isClassified')->willReturn(true); - $this->talkConfig->method('isSIPConfigured')->willReturn(true); + $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); + $this->assertTrue($isSIPConfigured); $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->phoneNumberUtil->expects(self::never()) ->method('convertToStandardFormat'); @@ -207,7 +213,8 @@ public function testFederatedUserInvitationsAreAcceptedForRegularConversation(): public function testPhoneInvitationsAreAcceptedForRegularConversation(): void { $currentUser = $this->createStub(IUser::class); - $this->talkConfig->method('isSIPConfigured')->willReturn(true); + $isSIPconfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); + $this->assertTrue($isSIPconfigured); $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->serverConfig->method('getSystemValueString')->willReturn('DE'); $this->phoneNumberUtil->method('convertToStandardFormat') diff --git a/tests/php/Service/ParticipantServiceParticipantTypeTest.php b/tests/php/Service/ParticipantServiceParticipantTypeTest.php index 91c1194d7a2..5d1d21d7aaf 100644 --- a/tests/php/Service/ParticipantServiceParticipantTypeTest.php +++ b/tests/php/Service/ParticipantServiceParticipantTypeTest.php @@ -22,6 +22,7 @@ use OCA\Talk\Service\MembershipService; use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\SessionService; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudIdManager; @@ -56,6 +57,7 @@ public function setUp(): void { protected function getConstructorArgs(): array { return [ $this->createMock(Config::class), + $this->createMock(IAppConfig::class), $this->attendeeMapper, $this->createMock(SessionMapper::class), $this->createMock(SessionService::class), diff --git a/tests/php/Service/ParticipantServiceTest.php b/tests/php/Service/ParticipantServiceTest.php index cb3b7442bb8..ffcf07cb412 100644 --- a/tests/php/Service/ParticipantServiceTest.php +++ b/tests/php/Service/ParticipantServiceTest.php @@ -21,6 +21,7 @@ use OCA\Talk\Service\SessionService; use OCA\Talk\Service\SIPDialOutService; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudIdManager; @@ -39,6 +40,7 @@ #[Group('DB')] class ParticipantServiceTest extends TestCase { protected Config&MockObject $talkConfig; + protected IAppConfig&MockObject $appConfig; protected ?AttendeeMapper $attendeeMapper = null; protected ?SessionMapper $sessionMapper = null; protected SessionService&MockObject $sessionService; @@ -59,6 +61,7 @@ public function setUp(): void { parent::setUp(); $this->talkConfig = $this->createMock(Config::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->attendeeMapper = new AttendeeMapper(\OCP\Server::get(IDBConnection::class)); $this->sessionMapper = new SessionMapper(\OCP\Server::get(IDBConnection::class)); $this->sessionService = $this->createMock(SessionService::class); @@ -75,6 +78,7 @@ public function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); $this->service = new ParticipantService( $this->talkConfig, + $this->appConfig, $this->attendeeMapper, $this->sessionMapper, $this->sessionService, From 182989b3190ca8f41d38300d3e10b6ebbf687ba1 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Thu, 8 Oct 2026 15:15:24 +0200 Subject: [PATCH 2/6] fix(sip): revert similar but distinct sip flags to individual settings Signed-off-by: Christian Lorang --- docs/settings.md | 2 +- lib/Capabilities.php | 2 +- lib/Config.php | 4 ++-- lib/ConfigLexicon.php | 2 +- lib/Controller/RoomController.php | 4 ++-- lib/Settings/Admin/AdminSettings.php | 2 +- src/components/AdminSettings/SIPBridge.vue | 4 ++-- tests/integration/features/callapi/sip-dialout.feature | 2 +- tests/integration/features/conversation-1/create.feature | 2 +- tests/integration/features/conversation-5/sip-dialout.feature | 2 +- tests/php/CapabilitiesTest.php | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/settings.md b/docs/settings.md index ba3712015f2..0d8ad784a91 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -126,7 +126,7 @@ Legend: | `call_recording_summary` | bool | `true` | No | 🖌️ | Whether call recordings should automatically be summarized when a transcription and summary provider is enabled. | | `call_recording_transcription` | bool | `false` | Yes | | Whether call recordings should automatically be transcribed when a transcription provider is enabled. | | `call_recording_summary_prompt` | string | `''` | No | | Instructions used by LLM to generate Talk call recording summaries | -| `sip_dialout` | string
`yes` or `no` | `no` | Yes | | SIP dial-out is allowed when a SIP bridge is configured | +| `sip_dialout` | bool | `false` | Yes | | SIP dial-out is allowed when a SIP bridge is configured | | `federation_enabled` | bool | `false` | Yes | | 🏗️ *Work in progress:* Whether or not federation with this instance is allowed | | `federation_incoming_enabled` | string
`1` or `0` | `1` | Yes | | 🏗️ *Work in progress:* Whether users of this instance can be invited to federated conversations | | `federation_outgoing_enabled` | string
`1` or `0` | `1` | Yes | | 🏗️ *Work in progress:* Whether users of this instance can invite federated users into conversations | diff --git a/lib/Capabilities.php b/lib/Capabilities.php index ba7ea5737b6..e0b5e4a1a4f 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -294,7 +294,7 @@ public function getCapabilities(): array { // 'predefined-backgrounds-v2' => list, 'can-upload-background' => false, 'sip-enabled' => !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)), - 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT), + 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_DIALOUT), 'default-phone-region' => $this->serverConfig->getSystemValueString('default_phone_region'), 'can-enable-sip' => false, 'start-without-media' => $this->talkConfig->getCallsStartWithoutMedia($user?->getUID()), diff --git a/lib/Config.php b/lib/Config.php index b621d0ccc08..ea0619f593f 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -111,7 +111,7 @@ class Config { public const string SIP_BRIDGE_DIALOUT_NUMBER = 'sip_bridge_dialout_number'; public const string SIP_BRIDGE_DIALOUT_PREFIX = 'sip_bridge_dialout_prefix'; public const string SIP_BRIDGE_SHARED_SECRET = 'sip_bridge_shared_secret'; - public const string SIP_BRIDGE_DIALOUT = 'sip_bridge_dialout'; + public const string SIP_DIALOUT = 'sip_dialout'; /** * 1. Call recording, … @@ -232,7 +232,7 @@ public function canUserEnableSIP(IUser $user): bool { } public function canUserDialOutSIP(IUser $user): bool { - if (!(!empty($this->appConfig->getAppValueString(self::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(self::SIP_BRIDGE_SHARED_SECRET)))) { + if (!$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { return false; } diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php index a01a85740f4..f9af14a89b0 100644 --- a/lib/ConfigLexicon.php +++ b/lib/ConfigLexicon.php @@ -219,7 +219,7 @@ public function getAppConfigs(): array { new Entry(Config::SIP_BRIDGE_DIALOUT_NUMBER, ValueType::STRING, '', definition: 'Fallback phone number that is used as caller for out-going calls when the user has no phone-number configured (has to be E164 `+49123456789` formatted'), new Entry(Config::SIP_BRIDGE_DIALOUT_PREFIX, ValueType::STRING, '+', definition: 'Prefix stat is added before the first configured phone-number of a user to make it a valid E164 number to be used as a caller for out-going calls'), new Entry(Config::SIP_BRIDGE_SHARED_SECRET, ValueType::STRING, '', definition: 'Shared secret allowing the SIP bridge to authenticate on the Nextcloud server', flags: IAppConfig::FLAG_SENSITIVE), - new Entry(Config::SIP_BRIDGE_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured', rename: 'sip_dialout'), + new Entry(Config::SIP_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured'), ]; } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 413d0360093..4bea78c73c1 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -2747,7 +2747,7 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse ])] public function verifyDialOutNumber(string $number, array $options = []): DataResponse { $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured) { + if (!$isSIPConfigured || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2846,7 +2846,7 @@ public function createGuestByDialIn(): DataResponse { ])] public function rejectedDialOutRequest(string $callId, array $options = []): DataResponse { $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured) { + if (!$isSIPConfigured || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php index 86afd759667..6e7c3abff2e 100644 --- a/lib/Settings/Admin/AdminSettings.php +++ b/lib/Settings/Admin/AdminSettings.php @@ -466,7 +466,7 @@ protected function initSIPBridge(): void { $this->initialState->provideInitialState('sip_bridge_groups', $groups); $this->initialState->provideInitialState('sip_bridge_shared_secret', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); $this->initialState->provideInitialState('sip_bridge_dialin_info', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)); - $this->initialState->provideInitialState('sip_bridge_dialout', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)); + $this->initialState->provideInitialState('sip_dialout', $this->appConfig->getAppValueBool(Config::SIP_DIALOUT)); $this->initialState->provideInitialState('sip_bridge_dialout_anonymous', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS)); $this->initialState->provideInitialState('sip_bridge_dialout_number', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_NUMBER)); $this->initialState->provideInitialState('sip_bridge_dialout_prefix', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_PREFIX)); diff --git a/src/components/AdminSettings/SIPBridge.vue b/src/components/AdminSettings/SIPBridge.vue index 7997c6d0966..b8555b6d384 100644 --- a/src/components/AdminSettings/SIPBridge.vue +++ b/src/components/AdminSettings/SIPBridge.vue @@ -204,7 +204,7 @@ export default { }) this.sipGroups = this.groups this.dialInInfo = loadState('spreed', 'sip_bridge_dialin_info') - this.dialOutEnabled = loadState('spreed', 'sip_bridge_dialout') + this.dialOutEnabled = loadState('spreed', 'sip_dialout') this.dialOutAnonymous = loadState('spreed', 'sip_bridge_dialout_anonymous') this.dialOutNumber = loadState('spreed', 'sip_bridge_dialout_number') this.dialOutPrefix = loadState('spreed', 'sip_bridge_dialout_prefix') @@ -266,7 +266,7 @@ export default { dialInInfo: this.dialInInfo, }) if (this.currentSetup.dialOutEnabled !== this.dialOutEnabled) { - await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout', this.dialOutEnabled) + await OCP.AppConfig.setValue('spreed', 'sip_dialout', this.dialOutEnabled) } if (this.currentSetup.dialOutAnonymous !== this.dialOutAnonymous) { await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout_anonymous', String(this.dialOutAnonymous)) diff --git a/tests/integration/features/callapi/sip-dialout.feature b/tests/integration/features/callapi/sip-dialout.feature index d17bef25290..0c4dab591e7 100644 --- a/tests/integration/features/callapi/sip-dialout.feature +++ b/tests/integration/features/callapi/sip-dialout.feature @@ -11,7 +11,7 @@ Feature: callapi/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_bridge_dialout | true | + | sip_dialout | true | And user "participant1" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/integration/features/conversation-1/create.feature b/tests/integration/features/conversation-1/create.feature index eb0305d0db8..8fa19b2069c 100644 --- a/tests/integration/features/conversation-1/create.feature +++ b/tests/integration/features/conversation-1/create.feature @@ -99,7 +99,7 @@ Feature: conversation-1/create | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_bridge_dialout | true | + | default_sip_dialout | true | # The default value is sent by clients without the user requesting SIP, # so it is disabled instead of failing the creation When user "participant1" creates room "room" (v4) diff --git a/tests/integration/features/conversation-5/sip-dialout.feature b/tests/integration/features/conversation-5/sip-dialout.feature index f28cdbc3d79..1e71d538332 100644 --- a/tests/integration/features/conversation-5/sip-dialout.feature +++ b/tests/integration/features/conversation-5/sip-dialout.feature @@ -31,7 +31,7 @@ Feature: conversation-5/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_bridge_dialout | true | + | sip_dialout | true | Given user "participant2" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php index 560e1dfeb31..8a0f1e30598 100644 --- a/tests/php/CapabilitiesTest.php +++ b/tests/php/CapabilitiesTest.php @@ -381,7 +381,7 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea ->willReturnMap([ ['backgrounds_default_for_users', true, true], ['backgrounds_upload_users', true, true], - ['sip_bridge_dialout', false], + ['sip_dialout', false], ['sip_bridge_dialout_anonymous', false], ]); From 154fd12491a905b24e50726a5ff6a68980ff36e3 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Tue, 13 Oct 2026 16:51:38 +0200 Subject: [PATCH 3/6] fix(test): rework tests with $isSIPConfigured to add callbacks for appconfig values checked by SIP configuration checks and remove redundant boolean asserts to itself Signed-off-by: Christian Lorang --- .../features/conversation-1/create.feature | 2 +- .../Controller/SignalingControllerTest.php | 12 +++++-- tests/php/Service/InvitationServiceTest.php | 33 +++++++++++++++---- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/tests/integration/features/conversation-1/create.feature b/tests/integration/features/conversation-1/create.feature index 8fa19b2069c..ba53224c2ae 100644 --- a/tests/integration/features/conversation-1/create.feature +++ b/tests/integration/features/conversation-1/create.feature @@ -99,7 +99,7 @@ Feature: conversation-1/create | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | default_sip_dialout | true | + | default_sip_enabled | 1 | # The default value is sent by clients without the user requesting SIP, # so it is disabled instead of failing the creation When user "participant1" creates room "room" (v4) diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index 62731a6622e..34a05478182 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -1512,13 +1512,19 @@ public function testGetSettingsSIPBridgeShortRandom(): void { public function testGetSettingsSIPBridgeValidNoToken(): void { $this->config = $this->createMock(Config::class); $this->appConfig = $this->createMock(IAppConfig::class); - $this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)->willReturn(self::SIP_BRIDGE_SECRET); $this->config->method('getStunServers')->willReturn([]); $this->config->method('getTurnSettings')->willReturn([]); $this->config->method('getSignalingMode')->willReturn(Config::SIGNALING_INTERNAL); $this->config->method('getHideSignalingWarning')->willReturn(false); - $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); - $this->assertFalse($isSIPConfigured); + + // when Config::SIP_BRIDGE_DIALIN_INFO is empty, SIP is not configured + $this->appConfig + ->method('getAppValueString') + ->willReturnCallback(fn (string $key): string => match ($key) { + Config::SIP_BRIDGE_DIALIN_INFO => '', + Config::SIP_BRIDGE_SHARED_SECRET => self::SIP_BRIDGE_SECRET, + }); + $this->userId = null; $this->recreateSignalingController(); diff --git a/tests/php/Service/InvitationServiceTest.php b/tests/php/Service/InvitationServiceTest.php index 7656ee07a30..46e703eca44 100644 --- a/tests/php/Service/InvitationServiceTest.php +++ b/tests/php/Service/InvitationServiceTest.php @@ -73,8 +73,15 @@ public function setUp(): void { public function testPhoneInvitationsAreRejectedWhenCreatingClassifiedConversation(): void { $currentUser = $this->createStub(IUser::class); // SIP is fully available, only the classified flag must reject the number - $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); - $this->assertTrue($isSIPConfigured); + + // when Config::SIP_BRIDGE_DIALIN_INFO and Config::SIP_BRIDGE_SECRET both are not empty, SIP is configured + $this->appConfig + ->method('getAppValueString') + ->willReturnCallback(fn (string $key): string => match ($key) { + Config::SIP_BRIDGE_DIALIN_INFO => Config::SIP_BRIDGE_DIALIN_INFO, + Config::SIP_BRIDGE_SHARED_SECRET => Config::SIP_BRIDGE_SHARED_SECRET, + }); + $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->phoneNumberUtil->expects(self::never()) ->method('convertToStandardFormat'); @@ -94,8 +101,15 @@ public function testPhoneInvitationsAreRejectedForClassifiedRoom(): void { $currentUser = $this->createStub(IUser::class); $room = $this->createMock(Room::class); $room->method('isClassified')->willReturn(true); - $isSIPConfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); - $this->assertTrue($isSIPConfigured); + + // when Config::SIP_BRIDGE_DIALIN_INFO and Config::SIP_BRIDGE_SECRET both are not empty, SIP is configured + $this->appConfig + ->method('getAppValueString') + ->willReturnCallback(fn (string $key): string => match ($key) { + Config::SIP_BRIDGE_DIALIN_INFO => Config::SIP_BRIDGE_DIALIN_INFO, + Config::SIP_BRIDGE_SHARED_SECRET => Config::SIP_BRIDGE_SHARED_SECRET, + }); + $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->phoneNumberUtil->expects(self::never()) ->method('convertToStandardFormat'); @@ -213,8 +227,15 @@ public function testFederatedUserInvitationsAreAcceptedForRegularConversation(): public function testPhoneInvitationsAreAcceptedForRegularConversation(): void { $currentUser = $this->createStub(IUser::class); - $isSIPconfigured = !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->method('getAppValueString')->with(Config::SIP_BRIDGE_SHARED_SECRET)); - $this->assertTrue($isSIPconfigured); + + // when Config::SIP_BRIDGE_DIALIN_INFO and CONFIG::SIP_BRIDGE_SECRET both are not empty, SIP is configured + $this->appConfig + ->method('getAppValueString') + ->willReturnCallback(fn (string $key): string => match ($key) { + Config::SIP_BRIDGE_DIALIN_INFO => Config::SIP_BRIDGE_DIALIN_INFO, + Config::SIP_BRIDGE_SHARED_SECRET => Config::SIP_BRIDGE_SHARED_SECRET, + }); + $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->serverConfig->method('getSystemValueString')->willReturn('DE'); $this->phoneNumberUtil->method('convertToStandardFormat') From 5fabae39e93b92f5d41111aa40d2e8a1c2797f86 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Tue, 13 Oct 2026 17:24:48 +0200 Subject: [PATCH 4/6] fix(settings): add .toString() to boolean value in frontend when sending value as json to backend for sip_dialout Signed-off-by: Christian Lorang --- src/components/AdminSettings/SIPBridge.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AdminSettings/SIPBridge.vue b/src/components/AdminSettings/SIPBridge.vue index b8555b6d384..c3428797219 100644 --- a/src/components/AdminSettings/SIPBridge.vue +++ b/src/components/AdminSettings/SIPBridge.vue @@ -266,7 +266,7 @@ export default { dialInInfo: this.dialInInfo, }) if (this.currentSetup.dialOutEnabled !== this.dialOutEnabled) { - await OCP.AppConfig.setValue('spreed', 'sip_dialout', this.dialOutEnabled) + await OCP.AppConfig.setValue('spreed', 'sip_dialout', this.dialOutEnabled.toString()) } if (this.currentSetup.dialOutAnonymous !== this.dialOutAnonymous) { await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout_anonymous', String(this.dialOutAnonymous)) From 364ae9af5a879da35b1737011039fdbd6b5d2867 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Mon, 19 Oct 2026 13:46:51 +0200 Subject: [PATCH 5/6] fix(sip): reinstate use of talkConfig isSIPConfigured() method instead of calling both app configs directly Signed-off-by: Christian Lorang --- lib/Capabilities.php | 2 +- lib/Controller/RoomController.php | 21 ++++++--------- lib/Controller/SignalingController.php | 2 +- lib/Manager.php | 2 +- lib/Service/InvitationService.php | 3 +-- lib/Service/ParticipantService.php | 4 +-- lib/Service/RoomFormatter.php | 4 +-- lib/SetupCheck/SIPConfiguration.php | 27 +------------------ .../conversation-4/classified.feature | 2 +- tests/php/Service/InvitationServiceTest.php | 21 ++------------- 10 files changed, 20 insertions(+), 68 deletions(-) diff --git a/lib/Capabilities.php b/lib/Capabilities.php index e0b5e4a1a4f..5748a1c7cf7 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -293,7 +293,7 @@ public function getCapabilities(): array { // 'predefined-backgrounds' => list, // 'predefined-backgrounds-v2' => list, 'can-upload-background' => false, - 'sip-enabled' => !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)), + 'sip-enabled' => $this->talkConfig->isSIPConfigured(), 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_DIALOUT), 'default-phone-region' => $this->serverConfig->getSystemValueString('default_phone_region'), 'can-enable-sip' => false, diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index 4bea78c73c1..dfdde814bca 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -834,7 +834,6 @@ public function createRoom( } $isClassified = $preset === Classified::getIdentifier(); - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); // Enabling SIP dial-in is restricted to the configured groups, so requesting // it at creation time requires the same permission as toggling it later on. @@ -844,7 +843,7 @@ public function createRoom( $sipEnabled = Webinary::SIP_DISABLED; } elseif ($sipEnabled !== Webinary::SIP_DISABLED && $this->forcedParameters->getForcedParameter(Parameter::SIP_ENABLED) === null - && (!$isSIPConfigured || !$this->talkConfig->canUserEnableSIP($user))) { + && (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->canUserEnableSIP($user))) { if ($sipEnabled === $this->defaultParameters->getParameters()[Parameter::SIP_ENABLED->value]) { // Clients send the administrator configured default value also when the // user did not request SIP themselves, so it is silently disabled instead. @@ -1432,7 +1431,7 @@ protected function formatParticipantList(array $participants, bool $includeStatu 'phoneNumber' => '', 'callId' => '', ]; - if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) + if ($this->talkConfig->isSIPConfigured() && $this->room->getSIPEnabled() !== Webinary::SIP_DISABLED && ($this->participant->hasModeratorPermissions(false) || $this->participant->getAttendee()->getId() === $participant->getAttendee()->getId())) { @@ -1512,7 +1511,7 @@ protected function formatParticipantList(array $participants, bool $includeStatu $result['displayName'] = $participant->getAttendee()->getDisplayName(); } elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_PHONES) { $result['displayName'] = $participant->getAttendee()->getDisplayName(); - if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) + if ($this->talkConfig->isSIPConfigured() && $this->participant->hasModeratorPermissions(false)) { $result['phoneNumber'] = $participant->getAttendee()->getPhoneNumber(); @@ -1684,7 +1683,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); if ( !$addedBy instanceof IUser - || !$isSIPConfigured + || !$this->talkConfig->isSIPConfigured() || !$this->talkConfig->canUserDialOutSIP($addedBy) || preg_match(Room::SIP_INCOMPATIBLE_REGEX, $this->room->getToken()) || ($this->room->getType() !== Room::TYPE_GROUP && $this->room->getType() !== Room::TYPE_PUBLIC)) { @@ -2656,8 +2655,7 @@ public function verifyDialInPin(#[SensitiveParameter] string $pin): DataResponse 'apiVersion' => '(v4)', ])] public function directDialIn(string $phoneNumber, string $caller): DataResponse { - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured) { + if (!$this->talkConfig->isSIPConfigured()) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2746,8 +2744,7 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse 'token' => '[a-z0-9]{4,30}', ])] public function verifyDialOutNumber(string $number, array $options = []): DataResponse { - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { + if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2845,8 +2842,7 @@ public function createGuestByDialIn(): DataResponse { 'token' => '[a-z0-9]{4,30}', ])] public function rejectedDialOutRequest(string $callId, array $options = []): DataResponse { - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { + if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -3317,8 +3313,7 @@ public function setSIPEnabled(int $state): DataResponse { return new DataResponse(['error' => 'config'], Http::STATUS_FORBIDDEN); } - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured) { + if (!$this->talkConfig->isSIPConfigured()) { return new DataResponse(['error' => 'config'], Http::STATUS_PRECONDITION_FAILED); } diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php index c5ab4ccbf91..21fdd081e63 100644 --- a/lib/Controller/SignalingController.php +++ b/lib/Controller/SignalingController.php @@ -271,7 +271,7 @@ public function getSettings(string $token = ''): DataResponse { 'federation' => $this->getFederationSettings($room), 'stunservers' => $stun, 'turnservers' => $turn, - 'sipDialinInfo' => !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) ? $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO) : '', + 'sipDialinInfo' => $this->talkConfig->isSIPConfigured() ? $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO) : '', ]; if ($signalingMode !== Config::SIGNALING_INTERNAL) { diff --git a/lib/Manager.php b/lib/Manager.php index aa135dc30b1..5f681662c75 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -1461,7 +1461,7 @@ protected function getRoomNameByParticipants(Room $room): string { */ protected function getNewToken(): string { $entropy = max(8, $this->appConfig->getAppValueInt(Config::TOKEN_ENTROPY)); // For update cases - $digitsOnly = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); + $digitsOnly = $this->talkConfig->isSIPConfigured(); if ($digitsOnly) { // Increase default token length as we only use numbers $entropy = max(10, $entropy); diff --git a/lib/Service/InvitationService.php b/lib/Service/InvitationService.php index b1594b3621d..15044f71207 100644 --- a/lib/Service/InvitationService.php +++ b/lib/Service/InvitationService.php @@ -194,8 +194,7 @@ protected function validatePhoneInvitations(InvitationList $invitationList, arra return; } - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); - if (!$isSIPConfigured || !$this->talkConfig->canUserDialOutSIP($currentUser)) { + if (!$this->talkConfig->isSIPConfigured() || !$this->talkConfig->canUserDialOutSIP($currentUser)) { $invitationList->setPhoneNumberResults([], $phoneNumbers); return; } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index 22ab1491cfe..f110b4fb06c 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -1171,7 +1171,7 @@ public function inviteEmailAddress(Room $room, string $actorId, string $email, ? } if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED - && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET))) { + && $this->talkConfig->isSIPConfigured()) { $attendee->setPin($this->generatePin()); } @@ -1190,7 +1190,7 @@ public function inviteEmailAddress(Room $room, string $actorId, string $email, ? public function generatePinForParticipant(Room $room, Participant $participant): void { $attendee = $participant->getAttendee(); if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED - && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) + && $this->talkConfig->isSIPConfigured() && ($attendee->getActorType() === Attendee::ACTOR_USERS || $attendee->getActorType() === Attendee::ACTOR_EMAILS) && !$attendee->getPin()) { $attendee->setPin($this->generatePin()); diff --git a/lib/Service/RoomFormatter.php b/lib/Service/RoomFormatter.php index f1f67b504c7..0498e3cdd25 100644 --- a/lib/Service/RoomFormatter.php +++ b/lib/Service/RoomFormatter.php @@ -269,7 +269,7 @@ public function formatRoomV4( } } - if (!empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET))) { + if ($this->talkConfig->isSIPConfigured()) { $roomData['sipEnabled'] = $room->getSIPEnabled(); if ($room->getSIPEnabled() !== Webinary::SIP_DISABLED) { // Generate a PIN if the attendee is a user and doesn't have one. @@ -351,7 +351,7 @@ public function formatRoomV4( } $roomData['canEnableSIP'] - = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)) + = $this->talkConfig->isSIPConfigured() && !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken()) && ($room->getType() === Room::TYPE_GROUP || $room->getType() === Room::TYPE_PUBLIC) && $currentParticipant->hasModeratorPermissions(false) diff --git a/lib/SetupCheck/SIPConfiguration.php b/lib/SetupCheck/SIPConfiguration.php index 2597e43f48c..a7497c182c5 100644 --- a/lib/SetupCheck/SIPConfiguration.php +++ b/lib/SetupCheck/SIPConfiguration.php @@ -42,32 +42,7 @@ public function run(): SetupResult { return SetupResult::success($this->l->t('Using the SIP functionality requires a High-performance backend.')); } - $query = $this->connection->getQueryBuilder(); - $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( - $this->connection->escapeLikeParameter('0') . '%' - ))); - - $result = $query->executeQuery(); - $invalidNumbers = $result->fetchFirstColumn(); - $result->closeCursor(); - - if (!empty($invalidNumbers)) { - $message = $this->l->t("Assigned Talk phone numbers must not start with + or 0. Please remove or update the following numbers:\n{list}"); - $message = str_replace( - '{list}', - implode("\n", $invalidNumbers), - $message - ); - return SetupResult::error($message, 'https://portal.nextcloud.com/article/Nextcloud-Talk/Nextcloud-Talk-Phone/Direct-Dial-in#content-provisioning'); - } - - if ($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET) === '' - && $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO) === '' + if (!$this->talkConfig->isSIPConfigured() && $this->appConfig->getAppValueInt(Config::FEATURE_HINTS_HIDDEN) < 34) { return SetupResult::info($this->l->t('No SIP backend configured')); } diff --git a/tests/integration/features/conversation-4/classified.feature b/tests/integration/features/conversation-4/classified.feature index f6fac3c5bb7..0545ab946a9 100644 --- a/tests/integration/features/conversation-4/classified.feature +++ b/tests/integration/features/conversation-4/classified.feature @@ -155,7 +155,7 @@ Feature: conversation-4/classified | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_bridge_dialout | true | + | sip_dialout | true | And user "participant1" creates room "classified" (v4) | roomType | 2 | | roomName | classified | diff --git a/tests/php/Service/InvitationServiceTest.php b/tests/php/Service/InvitationServiceTest.php index 46e703eca44..26dc27b11d1 100644 --- a/tests/php/Service/InvitationServiceTest.php +++ b/tests/php/Service/InvitationServiceTest.php @@ -72,16 +72,7 @@ public function setUp(): void { public function testPhoneInvitationsAreRejectedWhenCreatingClassifiedConversation(): void { $currentUser = $this->createStub(IUser::class); - // SIP is fully available, only the classified flag must reject the number - - // when Config::SIP_BRIDGE_DIALIN_INFO and Config::SIP_BRIDGE_SECRET both are not empty, SIP is configured - $this->appConfig - ->method('getAppValueString') - ->willReturnCallback(fn (string $key): string => match ($key) { - Config::SIP_BRIDGE_DIALIN_INFO => Config::SIP_BRIDGE_DIALIN_INFO, - Config::SIP_BRIDGE_SHARED_SECRET => Config::SIP_BRIDGE_SHARED_SECRET, - }); - + $this->talkConfig->method('isSIPConfigured')->willReturn(true); $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->phoneNumberUtil->expects(self::never()) ->method('convertToStandardFormat'); @@ -227,15 +218,7 @@ public function testFederatedUserInvitationsAreAcceptedForRegularConversation(): public function testPhoneInvitationsAreAcceptedForRegularConversation(): void { $currentUser = $this->createStub(IUser::class); - - // when Config::SIP_BRIDGE_DIALIN_INFO and CONFIG::SIP_BRIDGE_SECRET both are not empty, SIP is configured - $this->appConfig - ->method('getAppValueString') - ->willReturnCallback(fn (string $key): string => match ($key) { - Config::SIP_BRIDGE_DIALIN_INFO => Config::SIP_BRIDGE_DIALIN_INFO, - Config::SIP_BRIDGE_SHARED_SECRET => Config::SIP_BRIDGE_SHARED_SECRET, - }); - + $this->talkConfig->method('isSIPConfigured')->willReturn(true); $this->talkConfig->method('canUserDialOutSIP')->willReturn(true); $this->serverConfig->method('getSystemValueString')->willReturn('DE'); $this->phoneNumberUtil->method('convertToStandardFormat') From 1c3000abc986897dd7468abb7b0865dbdabbfad6 Mon Sep 17 00:00:00 2001 From: Christian Lorang Date: Mon, 26 Oct 2026 13:37:00 +0100 Subject: [PATCH 6/6] fix(sip): revert renaming of sip_bridge_dialout in initialState, align different names in other places instead Signed-off-by: Christian Lorang --- docs/settings.md | 4 ++-- lib/Capabilities.php | 2 +- lib/Config.php | 4 ++-- lib/ConfigLexicon.php | 4 ++-- lib/Controller/CallController.php | 3 --- lib/Controller/RoomController.php | 6 ++---- lib/Controller/SettingsController.php | 3 ++- lib/Service/InvitationService.php | 2 -- lib/Service/ParticipantService.php | 2 -- lib/Settings/Admin/AdminSettings.php | 2 +- src/components/AdminSettings/SIPBridge.vue | 4 ++-- tests/integration/features/callapi/sip-dialout.feature | 2 +- .../features/conversation-4/classified.feature | 2 +- .../features/conversation-5/sip-dialout.feature | 4 ++-- tests/php/CapabilitiesTest.php | 2 +- tests/php/Controller/SettingsControllerTest.php | 10 +++++++++- tests/php/Service/InvitationServiceTest.php | 1 - .../Service/ParticipantServiceParticipantTypeTest.php | 2 -- tests/php/Service/ParticipantServiceTest.php | 4 ---- 19 files changed, 28 insertions(+), 35 deletions(-) diff --git a/docs/settings.md b/docs/settings.md index 0d8ad784a91..edc862f21db 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -1,4 +1,4 @@ -# Settings API +# Settings API * Base endpoint: `/ocs/v2.php/apps/spreed/api/v1`: since Nextcloud 19 @@ -126,7 +126,7 @@ Legend: | `call_recording_summary` | bool | `true` | No | 🖌️ | Whether call recordings should automatically be summarized when a transcription and summary provider is enabled. | | `call_recording_transcription` | bool | `false` | Yes | | Whether call recordings should automatically be transcribed when a transcription provider is enabled. | | `call_recording_summary_prompt` | string | `''` | No | | Instructions used by LLM to generate Talk call recording summaries | -| `sip_dialout` | bool | `false` | Yes | | SIP dial-out is allowed when a SIP bridge is configured | +| `sip_bridge_dialout` | bool | `false` | Yes | | SIP dial-out is allowed when a SIP bridge is configured | | `federation_enabled` | bool | `false` | Yes | | 🏗️ *Work in progress:* Whether or not federation with this instance is allowed | | `federation_incoming_enabled` | string
`1` or `0` | `1` | Yes | | 🏗️ *Work in progress:* Whether users of this instance can be invited to federated conversations | | `federation_outgoing_enabled` | string
`1` or `0` | `1` | Yes | | 🏗️ *Work in progress:* Whether users of this instance can invite federated users into conversations | diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 5748a1c7cf7..8d4fda65650 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -294,7 +294,7 @@ public function getCapabilities(): array { // 'predefined-backgrounds-v2' => list, 'can-upload-background' => false, 'sip-enabled' => $this->talkConfig->isSIPConfigured(), - 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_DIALOUT), + 'sip-dialout-enabled' => $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT), 'default-phone-region' => $this->serverConfig->getSystemValueString('default_phone_region'), 'can-enable-sip' => false, 'start-without-media' => $this->talkConfig->getCallsStartWithoutMedia($user?->getUID()), diff --git a/lib/Config.php b/lib/Config.php index ea0619f593f..5f2cb691b94 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -111,7 +111,7 @@ class Config { public const string SIP_BRIDGE_DIALOUT_NUMBER = 'sip_bridge_dialout_number'; public const string SIP_BRIDGE_DIALOUT_PREFIX = 'sip_bridge_dialout_prefix'; public const string SIP_BRIDGE_SHARED_SECRET = 'sip_bridge_shared_secret'; - public const string SIP_DIALOUT = 'sip_dialout'; + public const string SIP_BRIDGE_DIALOUT = 'sip_bridge_dialout'; /** * 1. Call recording, … @@ -232,7 +232,7 @@ public function canUserEnableSIP(IUser $user): bool { } public function canUserDialOutSIP(IUser $user): bool { - if (!$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { + if (!$this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)) { return false; } diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php index f9af14a89b0..82e73f34dc3 100644 --- a/lib/ConfigLexicon.php +++ b/lib/ConfigLexicon.php @@ -217,9 +217,9 @@ public function getAppConfigs(): array { new Entry(Config::SIP_BRIDGE_DIALIN_INFO, ValueType::STRING, '', definition: 'Additional information added in the SIP dial-in invitation mail and sidebar', flags: IAppConfig::FLAG_SENSITIVE), new Entry(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS, ValueType::BOOL, false, definition: 'When set to true, all out-going SIP calls will be anonymous calls (CLIR)'), new Entry(Config::SIP_BRIDGE_DIALOUT_NUMBER, ValueType::STRING, '', definition: 'Fallback phone number that is used as caller for out-going calls when the user has no phone-number configured (has to be E164 `+49123456789` formatted'), - new Entry(Config::SIP_BRIDGE_DIALOUT_PREFIX, ValueType::STRING, '+', definition: 'Prefix stat is added before the first configured phone-number of a user to make it a valid E164 number to be used as a caller for out-going calls'), + new Entry(Config::SIP_BRIDGE_DIALOUT_PREFIX, ValueType::STRING, '+', definition: 'Deprecated: Only used for direct dial-in from older SIP bridges, which send phone numbers without this prefix', deprecated: true), new Entry(Config::SIP_BRIDGE_SHARED_SECRET, ValueType::STRING, '', definition: 'Shared secret allowing the SIP bridge to authenticate on the Nextcloud server', flags: IAppConfig::FLAG_SENSITIVE), - new Entry(Config::SIP_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured'), + new Entry(Config::SIP_BRIDGE_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured', rename: 'sip_dialout'), ]; } diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php index c49907ee123..3e77a45d52e 100644 --- a/lib/Controller/CallController.php +++ b/lib/Controller/CallController.php @@ -474,9 +474,6 @@ public function sipDialOut(int $attendeeId): DataResponse { $numbers = $this->phoneNumberMapper->findByUser($attendee->getActorId()); if (!empty($numbers)) { $callerNumber = array_shift($numbers)->getPhoneNumber(); - $number = array_shift($numbers); - $callerNumber = $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_PREFIX); - $callerNumber .= $number->getPhoneNumber(); } } } diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index dfdde814bca..ee26d8ad54a 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -1680,7 +1680,6 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u return new DataResponse(['error' => 'classified'], Http::STATUS_BAD_REQUEST); } - $isSIPConfigured = !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)) && !empty($this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); if ( !$addedBy instanceof IUser || !$this->talkConfig->isSIPConfigured() @@ -2604,7 +2603,6 @@ public function joinFederatedRoom(string $token, ?string $sessionId): DataRespon 'apiVersion' => '(v4)', 'token' => '[a-z0-9]{4,30}', ])] - public function verifyDialInPin(#[SensitiveParameter] string $pin): DataResponse { if (!$this->talkConfig->isSIPConfigured()) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); @@ -2744,7 +2742,7 @@ public function directDialIn(string $phoneNumber, string $caller): DataResponse 'token' => '[a-z0-9]{4,30}', ])] public function verifyDialOutNumber(string $number, array $options = []): DataResponse { - if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { + if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } @@ -2842,7 +2840,7 @@ public function createGuestByDialIn(): DataResponse { 'token' => '[a-z0-9]{4,30}', ])] public function rejectedDialOutRequest(string $callId, array $options = []): DataResponse { - if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_DIALOUT)) { + if (!$this->talkConfig->isSIPConfigured() || !$this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)) { return new DataResponse(null, Http::STATUS_NOT_IMPLEMENTED); } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 22c48fe55bc..20576ffc14d 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -9,6 +9,7 @@ namespace OCA\Talk\Controller; use OCA\Talk\AuditLog\Operation; +use OCA\Talk\Config; use OCA\Talk\Settings\BeforePreferenceSetEventListener; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\ApiRoute; @@ -16,8 +17,8 @@ use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; -use OCP\EventDispatcher\IEventDispatcher; use OCP\AppFramework\Services\IAppConfig; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; diff --git a/lib/Service/InvitationService.php b/lib/Service/InvitationService.php index 15044f71207..9f6d41a59b0 100644 --- a/lib/Service/InvitationService.php +++ b/lib/Service/InvitationService.php @@ -15,7 +15,6 @@ use OCA\Talk\Model\InvitationList; use OCA\Talk\Room; use OCP\App\IAppManager; -use OCP\AppFramework\Services\IAppConfig; use OCP\Federation\ICloudIdManager; use OCP\IConfig; use OCP\IGroup; @@ -36,7 +35,6 @@ public function __construct( private readonly ParticipantService $participantService, private readonly IConfig $serverConfig, private readonly Config $talkConfig, - private readonly IAppConfig $appConfig, private readonly IEmailValidator $emailValidator, ) { } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index f110b4fb06c..1b767321f85 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -64,7 +64,6 @@ use OCA\Talk\Webinary; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; -use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Comments\IComment; use OCP\DB\Exception; @@ -122,7 +121,6 @@ class ParticipantService { public function __construct( private readonly Config $talkConfig, - private readonly IAppConfig $appConfig, private readonly AttendeeMapper $attendeeMapper, private readonly SessionMapper $sessionMapper, private readonly SessionService $sessionService, diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php index 6e7c3abff2e..86afd759667 100644 --- a/lib/Settings/Admin/AdminSettings.php +++ b/lib/Settings/Admin/AdminSettings.php @@ -466,7 +466,7 @@ protected function initSIPBridge(): void { $this->initialState->provideInitialState('sip_bridge_groups', $groups); $this->initialState->provideInitialState('sip_bridge_shared_secret', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_SHARED_SECRET)); $this->initialState->provideInitialState('sip_bridge_dialin_info', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALIN_INFO)); - $this->initialState->provideInitialState('sip_dialout', $this->appConfig->getAppValueBool(Config::SIP_DIALOUT)); + $this->initialState->provideInitialState('sip_bridge_dialout', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)); $this->initialState->provideInitialState('sip_bridge_dialout_anonymous', $this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT_ANONYMOUS)); $this->initialState->provideInitialState('sip_bridge_dialout_number', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_NUMBER)); $this->initialState->provideInitialState('sip_bridge_dialout_prefix', $this->appConfig->getAppValueString(Config::SIP_BRIDGE_DIALOUT_PREFIX)); diff --git a/src/components/AdminSettings/SIPBridge.vue b/src/components/AdminSettings/SIPBridge.vue index c3428797219..eb1da0d4db5 100644 --- a/src/components/AdminSettings/SIPBridge.vue +++ b/src/components/AdminSettings/SIPBridge.vue @@ -204,7 +204,7 @@ export default { }) this.sipGroups = this.groups this.dialInInfo = loadState('spreed', 'sip_bridge_dialin_info') - this.dialOutEnabled = loadState('spreed', 'sip_dialout') + this.dialOutEnabled = loadState('spreed', 'sip_bridge_dialout') this.dialOutAnonymous = loadState('spreed', 'sip_bridge_dialout_anonymous') this.dialOutNumber = loadState('spreed', 'sip_bridge_dialout_number') this.dialOutPrefix = loadState('spreed', 'sip_bridge_dialout_prefix') @@ -266,7 +266,7 @@ export default { dialInInfo: this.dialInInfo, }) if (this.currentSetup.dialOutEnabled !== this.dialOutEnabled) { - await OCP.AppConfig.setValue('spreed', 'sip_dialout', this.dialOutEnabled.toString()) + await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout', this.dialOutEnabled.toString()) } if (this.currentSetup.dialOutAnonymous !== this.dialOutAnonymous) { await OCP.AppConfig.setValue('spreed', 'sip_bridge_dialout_anonymous', String(this.dialOutAnonymous)) diff --git a/tests/integration/features/callapi/sip-dialout.feature b/tests/integration/features/callapi/sip-dialout.feature index 0c4dab591e7..5649246fb2b 100644 --- a/tests/integration/features/callapi/sip-dialout.feature +++ b/tests/integration/features/callapi/sip-dialout.feature @@ -11,7 +11,7 @@ Feature: callapi/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | true | + | sip_bridge_dialout| true | And user "participant1" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/integration/features/conversation-4/classified.feature b/tests/integration/features/conversation-4/classified.feature index 0545ab946a9..2b1f04e7aee 100644 --- a/tests/integration/features/conversation-4/classified.feature +++ b/tests/integration/features/conversation-4/classified.feature @@ -155,7 +155,7 @@ Feature: conversation-4/classified | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | true | + | sip_bridge_dialout | true | And user "participant1" creates room "classified" (v4) | roomType | 2 | | roomName | classified | diff --git a/tests/integration/features/conversation-5/sip-dialout.feature b/tests/integration/features/conversation-5/sip-dialout.feature index 1e71d538332..d1c20a5b4f4 100644 --- a/tests/integration/features/conversation-5/sip-dialout.feature +++ b/tests/integration/features/conversation-5/sip-dialout.feature @@ -10,7 +10,7 @@ Feature: conversation-5/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | true | + | sip_bridge_dialout| true | Given user "participant1" creates room "room" (v4) | roomType | 3 | | roomName | room | @@ -31,7 +31,7 @@ Feature: conversation-5/sip-dialout | sip_bridge_dialin_info | +49-1234-567890 | | sip_bridge_shared_secret | 1234567890abcdef | | sip_bridge_groups | ["group1"] | - | sip_dialout | true | + | sip_bridge_dialout| true | Given user "participant2" creates room "room" (v4) | roomType | 3 | | roomName | room | diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php index 8a0f1e30598..560e1dfeb31 100644 --- a/tests/php/CapabilitiesTest.php +++ b/tests/php/CapabilitiesTest.php @@ -381,7 +381,7 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea ->willReturnMap([ ['backgrounds_default_for_users', true, true], ['backgrounds_upload_users', true, true], - ['sip_dialout', false], + ['sip_bridge_dialout', false], ['sip_bridge_dialout_anonymous', false], ]); diff --git a/tests/php/Controller/SettingsControllerTest.php b/tests/php/Controller/SettingsControllerTest.php index 299ecb8c7e4..ce4044c1549 100644 --- a/tests/php/Controller/SettingsControllerTest.php +++ b/tests/php/Controller/SettingsControllerTest.php @@ -8,8 +8,10 @@ namespace OCA\Talk\Tests\php\Controller; +use OCA\Talk\Config; use OCA\Talk\Controller\SettingsController; use OCA\Talk\Settings\BeforePreferenceSetEventListener; +use OCP\AppFramework\Services\IAppConfig; use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IGroup; @@ -22,6 +24,7 @@ class SettingsControllerTest extends TestCase { protected IConfig&MockObject $config; + protected IAppConfig&MockObject $appConfig; protected IGroupManager&MockObject $groupManager; protected IEventDispatcher&MockObject $dispatcher; protected SettingsController $controller; @@ -30,12 +33,14 @@ public function setUp(): void { parent::setUp(); $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->dispatcher = $this->createMock(IEventDispatcher::class); $this->controller = new SettingsController( 'spreed', $this->createMock(IRequest::class), $this->config, + $this->appConfig, $this->groupManager, $this->createMock(BeforePreferenceSetEventListener::class), 'admin', @@ -58,7 +63,10 @@ public function testSetSIPSettingsLogsCriticalAction(string $oldSecret, string $ ['sip-users', $group], ['unknown', null], ]); - $this->config->method('getAppValue')->with('spreed', 'sip_bridge_shared_secret')->willReturn($oldSecret); + + $this->appConfig->method('getAppValueString')->willReturnMap([ + [Config::SIP_BRIDGE_SHARED_SECRET, $oldSecret], + ]); $this->dispatcher->expects($this->once()) ->method('dispatchTyped') diff --git a/tests/php/Service/InvitationServiceTest.php b/tests/php/Service/InvitationServiceTest.php index 26dc27b11d1..f8fce7fb5b4 100644 --- a/tests/php/Service/InvitationServiceTest.php +++ b/tests/php/Service/InvitationServiceTest.php @@ -65,7 +65,6 @@ public function setUp(): void { $this->participantService, $this->serverConfig, $this->talkConfig, - $this->appConfig, $this->emailValidator, ); } diff --git a/tests/php/Service/ParticipantServiceParticipantTypeTest.php b/tests/php/Service/ParticipantServiceParticipantTypeTest.php index 5d1d21d7aaf..91c1194d7a2 100644 --- a/tests/php/Service/ParticipantServiceParticipantTypeTest.php +++ b/tests/php/Service/ParticipantServiceParticipantTypeTest.php @@ -22,7 +22,6 @@ use OCA\Talk\Service\MembershipService; use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\SessionService; -use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudIdManager; @@ -57,7 +56,6 @@ public function setUp(): void { protected function getConstructorArgs(): array { return [ $this->createMock(Config::class), - $this->createMock(IAppConfig::class), $this->attendeeMapper, $this->createMock(SessionMapper::class), $this->createMock(SessionService::class), diff --git a/tests/php/Service/ParticipantServiceTest.php b/tests/php/Service/ParticipantServiceTest.php index ffcf07cb412..cb3b7442bb8 100644 --- a/tests/php/Service/ParticipantServiceTest.php +++ b/tests/php/Service/ParticipantServiceTest.php @@ -21,7 +21,6 @@ use OCA\Talk\Service\SessionService; use OCA\Talk\Service\SIPDialOutService; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudIdManager; @@ -40,7 +39,6 @@ #[Group('DB')] class ParticipantServiceTest extends TestCase { protected Config&MockObject $talkConfig; - protected IAppConfig&MockObject $appConfig; protected ?AttendeeMapper $attendeeMapper = null; protected ?SessionMapper $sessionMapper = null; protected SessionService&MockObject $sessionService; @@ -61,7 +59,6 @@ public function setUp(): void { parent::setUp(); $this->talkConfig = $this->createMock(Config::class); - $this->appConfig = $this->createMock(IAppConfig::class); $this->attendeeMapper = new AttendeeMapper(\OCP\Server::get(IDBConnection::class)); $this->sessionMapper = new SessionMapper(\OCP\Server::get(IDBConnection::class)); $this->sessionService = $this->createMock(SessionService::class); @@ -78,7 +75,6 @@ public function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); $this->service = new ParticipantService( $this->talkConfig, - $this->appConfig, $this->attendeeMapper, $this->sessionMapper, $this->sessionService,