diff --git a/lib/BackgroundJob/CheckHostedSignalingServer.php b/lib/BackgroundJob/CheckHostedSignalingServer.php index 72b19d13a58..35d26c32798 100644 --- a/lib/BackgroundJob/CheckHostedSignalingServer.php +++ b/lib/BackgroundJob/CheckHostedSignalingServer.php @@ -129,21 +129,14 @@ protected function run($argument): void { if ($oldStatus !== $newStatus) { if ($newStatus === 'deleted') { // remove signaling servers if account is not active anymore - $this->appConfig->deleteAppValue('signaling_servers'); - //$this->config->deleteAppValue('spreed', 'signaling_servers'); + $this->appConfig->deleteAppValue(Config::SIGNALING_SERVERS_SECRET); + $this->appConfig->deleteAppValue(Config::SIGNALING_SERVERS); $notificationSubject = 'removed'; } elseif ($newStatus === 'active') { // add signaling servers if account got active - $this->appConfig->setAppValueArray('signaling_servers', [ - 'servers' => [ - [ - 'server' => $accountInfo['signaling']['url'], - 'verify' => true, - ] - ], - 'secret' => $accountInfo['signaling']['secret'], - ]); + $this->appConfig->setAppValueArray(Config::SIGNALING_SERVERS, ['servers' => [['server' => $accountInfo['signaling']['url'], 'verify' => true]], 'secret' => $accountInfo['signaling']['secret']]); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, $accountInfo['signaling']['secret']); $this->updateStunTurnSettings($oldAccountInfo, $accountInfo); $notificationSubject = 'added'; @@ -161,15 +154,8 @@ protected function run($argument): void { } elseif ($newStatus === 'active') { if ($oldAccountInfo['signaling']['url'] !== $accountInfo['signaling']['url'] || $oldAccountInfo['signaling']['secret'] !== $accountInfo['signaling']['secret']) { - $this->appConfig->setAppValueArray('signaling_servers', [ - 'servers' => [ - [ - 'server' => $accountInfo['signaling']['url'], - 'verify' => true, - ] - ], - 'secret' => $accountInfo['signaling']['secret'], - ]); + $this->appConfig->setAppValueArray(Config::SIGNALING_SERVERS, ['servers' => ['server' => $accountInfo['signaling']['url'], 'verify' => true], 'secret' => $accountInfo['signaling']['secret']]); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, $accountInfo['signaling']['secret']); } $this->updateStunTurnSettings($oldAccountInfo, $accountInfo); } diff --git a/lib/Capabilities.php b/lib/Capabilities.php index ec77d2ecf9d..7229ead1969 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -315,7 +315,7 @@ public function getCapabilities(): array { 'typing-privacy' => Participant::PRIVACY_PUBLIC, 'summary-threshold' => max(1, $this->appConfig->getAppValueInt(Config::SUMMARY_THRESHOLD)), 'style' => $this->talkConfig->getChatStyle($user?->getUID()), - 'matterbridge-enabled' => $user instanceof IUser && $this->serverConfig->getAppValue('spreed', 'enable_matterbridge', '0') === '1', + 'matterbridge-enabled' => $user instanceof IUser && $this->appConfig->getAppValueBool(Config::MATTERBRIDGE_ENABLED), ], 'conversations' => [ 'can-create' => $user instanceof IUser && !$this->talkConfig->isNotAllowedToCreateConversations($user), diff --git a/lib/Chat/Notifier.php b/lib/Chat/Notifier.php index bf31c884c54..4ef421fabac 100644 --- a/lib/Chat/Notifier.php +++ b/lib/Chat/Notifier.php @@ -22,7 +22,6 @@ use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Comments\IComment; -use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; use OCP\IUserManager; @@ -47,7 +46,6 @@ public function __construct( private readonly IGroupManager $groupManager, private readonly ParticipantService $participantService, private readonly ThreadService $threadService, - private readonly IConfig $config, private readonly IAppConfig $appConfig, private readonly ITimeFactory $timeFactory, private readonly Util $util, diff --git a/lib/Command/Signaling/Add.php b/lib/Command/Signaling/Add.php index 8967d4506d4..222bdd1eb23 100644 --- a/lib/Command/Signaling/Add.php +++ b/lib/Command/Signaling/Add.php @@ -9,7 +9,8 @@ namespace OCA\Talk\Command\Signaling; use OC\Core\Command\Base; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -18,7 +19,7 @@ class Add extends Base { public function __construct( - private readonly IConfig $config, + private readonly IAppConfig $appConfig, ) { parent::__construct(); } @@ -59,13 +60,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $config = $this->config->getAppValue('spreed', 'signaling_servers'); + $signaling_servers = $this->appConfig->getAppValueArray(Config::SIGNALING_SERVERS); - $signaling = json_decode($config, true); - if ($signaling === null || empty($signaling) || !is_array($signaling)) { + if (empty($signaling_servers)) { $servers = []; } else { - $servers = is_array($signaling['servers']) ? $signaling['servers'] : []; + $servers = $signaling_servers['servers']; } $servers[] = [ 'server' => $server, @@ -76,7 +76,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int 'secret' => $secret, ]; - $this->config->setAppValue('spreed', 'signaling_servers', json_encode($signaling)); + $this->appConfig->setAppValueArray(Config::SIGNALING_SERVERS, $signaling); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, $signaling['secret']); $output->writeln('Added signaling server ' . $server . '.'); return 0; } diff --git a/lib/Command/Signaling/Delete.php b/lib/Command/Signaling/Delete.php index a6a42dbbc7f..3423eda454b 100644 --- a/lib/Command/Signaling/Delete.php +++ b/lib/Command/Signaling/Delete.php @@ -9,7 +9,8 @@ namespace OCA\Talk\Command\Signaling; use OC\Core\Command\Base; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -17,7 +18,7 @@ class Delete extends Base { public function __construct( - private readonly IConfig $config, + private readonly IAppConfig $appConfig, ) { parent::__construct(); } @@ -37,9 +38,8 @@ protected function configure(): void { protected function execute(InputInterface $input, OutputInterface $output): int { $server = $input->getArgument('server'); - $config = $this->config->getAppValue('spreed', 'signaling_servers'); - $signaling = json_decode($config, true); - if ($signaling === null || empty($signaling) || !is_array($signaling)) { + $signaling = $this->appConfig->getAppValueArray(Config::SIGNALING_SERVERS); + if (empty($signaling)) { $signaling = [ 'servers' => [], 'secret' => '', @@ -50,7 +50,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $servers = array_filter($signaling['servers'], fn ($s) => $s['server'] !== $server); $signaling['servers'] = array_values($servers); // reindex - $this->config->setAppValue('spreed', 'signaling_servers', json_encode($signaling)); + $this->appConfig->setAppValueArray(Config::SIGNALING_SERVERS, $signaling); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, $signaling['secret']); if ($count > count($signaling['servers'])) { $output->writeln('Deleted ' . $server . '.'); } else { diff --git a/lib/Command/Signaling/ListCommand.php b/lib/Command/Signaling/ListCommand.php index d306c91528c..bee4c618a35 100644 --- a/lib/Command/Signaling/ListCommand.php +++ b/lib/Command/Signaling/ListCommand.php @@ -9,14 +9,15 @@ namespace OCA\Talk\Command\Signaling; use OC\Core\Command\Base; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class ListCommand extends Base { public function __construct( - private readonly IConfig $config, + private readonly IAppConfig $appConfig, ) { parent::__construct(); } @@ -31,11 +32,7 @@ protected function configure(): void { } protected function execute(InputInterface $input, OutputInterface $output): int { - $config = $this->config->getAppValue('spreed', 'signaling_servers'); - $signaling = json_decode($config, true); - if (!is_array($signaling)) { - $signaling = []; - } + $signaling = $this->appConfig->getAppValueArray(Config::SIGNALING_SERVERS); $this->writeMixedInOutputFormat($input, $output, $signaling); return 0; diff --git a/lib/Command/Signaling/VerifyKeys.php b/lib/Command/Signaling/VerifyKeys.php index 3dcfba796be..a58a6285559 100644 --- a/lib/Command/Signaling/VerifyKeys.php +++ b/lib/Command/Signaling/VerifyKeys.php @@ -10,7 +10,7 @@ use OC\Core\Command\Base; use OCA\Talk\Config; -use OCP\IConfig; +use OCP\AppFramework\Services\IAppConfig; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -18,8 +18,8 @@ class VerifyKeys extends Base { public function __construct( - private readonly IConfig $config, private readonly Config $talkConfig, + private readonly IAppConfig $appConfig, ) { parent::__construct(); } @@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($update) { $output->writeln('Stored public key for algorithm ' . strtolower($alg) . ' did not match stored private key.'); $output->writeln('A new public key was created and stored.'); - $this->config->setAppValue('spreed', 'signaling_token_pubkey_' . strtolower($alg), $publicKeyDerived); + $this->appConfig->setAppValueString('signaling_token_pubkey_' . strtolower($alg), $publicKeyDerived); return 0; } diff --git a/lib/Config.php b/lib/Config.php index 4ec96fe33ae..77ce7eb2797 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -41,6 +41,9 @@ class Config { public const SIGNALING_TICKET_V2 = 2; public const string RETENTION_CLASSIFIED_ROOMS = 'retention_classified_rooms'; + public const string RETENTION_EVENT_ROOMS = 'retention_event_rooms'; + public const string RETENTION_PHONE_ROOMS = 'retention_phone_rooms'; + public const string RETENTION_INSTANT_MEETINGS = 'retention_instant_meetings'; public const string STUN_SERVERS = 'stun_servers'; public const string TURN_SERVERS = 'turn_servers'; public const string DEFAULT_STUN_SERVER = 'stun.nextcloud.com:443'; @@ -52,10 +55,13 @@ class Config { public const string FEDERATION_INCOMING_ENABLED = 'federation_incoming_enabled'; public const string FEDERATION_OUTGOING_ENABLED = 'federation_outgoing_enabled'; public const string FEDERATION_ONLY_TRUSTED_SERVERS = 'federation_only_trusted_servers'; + public const string ALLOWED_START_CALLS = 'start_calls'; + public const string ALLOWED_START_CALLS_GROUPS = 'start_calls_groups'; public const string BREAKOUT_ROOMS_ENABLED = 'breakout_rooms'; public const string CONVERSATION_SUBFOLDERS = 'conversation_subfolders'; public const string CONVERSATIONS_FILES = 'conversations_files'; public const string CONVERSATIONS_FILES_PUBLIC_SHARES = 'conversations_files_public_shares'; + public const string DEFAULT_GROUP_NOTIFICATION = 'default_group_notification'; public const string DEFAULT_ROOM_PERMISSIONS = 'default_permissions'; public const string DEFAULT_ATTACHMENT_FOLDER = 'default_attachment_folder'; public const string GRID_VIDEOS_LIMIT = 'grid_videos_limit'; @@ -85,6 +91,7 @@ class Config { public const string BACKGROUNDS_DEFAULT_FOR_USERS = 'backgrounds_default_for_users'; public const string BACKGROUNDS_UPLOAD_USERS = 'backgrounds_upload_users'; public const string CREATE_SAMPLES = 'create_samples'; + public const string SAMPLES_DIRECTORY = 'samples_directory'; public const string MATTERBRIDGE_ENABLED = 'enable_matterbridge'; public const string MATRIX_ENABLED = 'matrix_enabled'; public const string MATRIX_ALLOWED_GROUPS = 'matrix_allowed_groups'; @@ -93,30 +100,30 @@ class Config { public const string CERTIFICATE_EXPIRATION_DAYS = 'certificate_expiration_days'; public const string TOKEN_ENTROPY = 'token_entropy'; public const string SUMMARY_THRESHOLD = 'summary_threshold'; - public const string ALLOWED_START_CALLS = 'start_calls'; - public const string SAMPLES_DIRECTORY = 'samples_directory'; - public const string RETENTION_EVENT_ROOMS = 'retention_event_rooms'; - public const string RETENTION_PHONE_ROOMS = 'retention_phone_rooms'; - public const string RETENTION_INSTANT_MEETINGS = 'retention_instant_meetings'; public const string MAX_CALL_DURATION = 'max_call_duration'; public const string FEATURE_HINTS_HIDDEN = 'feature_hints_hidden'; public const string MATTERBRIDGE_BINARY = 'matterbridge_binary'; public const string MATTERBRIDGE_BOT_PASSWORD = 'bridge_bot_password'; - public const string DEFAULT_GROUP_NOTIFICATION = 'default_group_notification'; public const string CHAT_STYLE = 'chat_style'; public const string CONVERSATIONS_LIST_STYLE = 'conversations_list_style'; public const string HIDE_SIGNALING_WARNING = 'hide_signaling_warning'; public const string CHANGELOG = 'changelog'; public const string SESSION_PING_LIMIT = 'session_ping_limit'; - public const string HOSTED_SIGNALING_SERVER_ACCOUNT = 'hosted_signaling_server_account'; + public const string CONVERSATIONS_LIST_STYLES = 'conversations_list_styles'; + public const string SIGNALING_TICKET_SECRET = 'signaling_ticket_secret'; + public const string SIGNALING_TOKEN_ALG = 'signaling_token_alg'; 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 HOSTED_SIGNALING_SERVER_ACCOUNT = 'hosted_signaling_server_account'; + public const string SIGNALING_SERVERS = 'signaling_servers'; + public const string SIGNALING_SERVERS_SECRET = 'signaling_servers_secret'; 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'; + public const string SIP_DIALIN_DEFAULT = 'sip_dialin_default'; /** * 1. Call recording, … @@ -237,7 +244,7 @@ public function canUserEnableSIP(IUser $user): bool { } public function canUserDialOutSIP(IUser $user): bool { - if (!$this->appConfig->getAppValueBool(Config::SIP_BRIDGE_DIALOUT)) { + if (!$this->appConfig->getAppValueBool(self::SIP_BRIDGE_DIALOUT)) { return false; } @@ -514,13 +521,13 @@ protected function getWebSocketDomainForSignalingServer(string $url): string { * @return string[] */ public function getStunServers(): array { - $servers = $this->appConfig->getAppValueArray(Config::STUN_SERVERS); + $servers = $this->appConfig->getAppValueArray(self::STUN_SERVERS); if (empty($servers)) { - $servers = [Config::DEFAULT_STUN_SERVER]; + $servers = [self::DEFAULT_STUN_SERVER]; } if (!$this->config->getSystemValueBool('has_internet_connection', true)) { - $servers = array_filter($servers, static fn ($server) => $server !== Config::DEFAULT_STUN_SERVER); + $servers = array_filter($servers, static fn ($server) => $server !== self::DEFAULT_STUN_SERVER); } return $servers; @@ -671,31 +678,25 @@ public function getSignalingMode(): string { * @return array */ public function getSignalingServers(): array { - $config = $this->config->getAppValue('spreed', 'signaling_servers'); - $signaling = json_decode($config, true); - if (!is_array($signaling) || !isset($signaling['servers'])) { + $config = $this->appConfig->getAppValueArray(self::SIGNALING_SERVERS); + + if (!array_key_exists('servers', $config)) { return []; } - return $signaling['servers']; + return $config['servers']; } /** * @return string */ public function getSignalingSecret(): string { - $config = $this->config->getAppValue('spreed', 'signaling_servers'); - $signaling = json_decode($config, true); - - if (!is_array($signaling)) { - return ''; - } - - return $signaling['secret']; + $config = $this->appConfig->getAppValueArray(self::SIGNALING_SERVERS); + return $config['secret'] ?? ''; } public function getHideSignalingWarning(): bool { - return $this->appConfig->getAppValueBool(Config::HIDE_SIGNALING_WARNING); + return $this->appConfig->getAppValueBool(self::HIDE_SIGNALING_WARNING); } /** @@ -716,7 +717,7 @@ public function getSignalingTicket(int $version, ?string $userId, ?string $cloud */ private function getSignalingTicketV1(?string $userId): string { if (empty($userId)) { - $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret'); + $secret = $this->appConfig->getAppValueString(self::SIGNALING_TICKET_SECRET); } else { $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret'); } @@ -725,7 +726,7 @@ private function getSignalingTicketV1(?string $userId): string { // TODO(fancycode): Is there a possibility for a race condition? $secret = $this->secureRandom->generate(255); if (empty($userId)) { - $this->config->setAppValue('spreed', 'signaling_ticket_secret', $secret); + $this->appConfig->setAppValueString(self::SIGNALING_TICKET_SECRET, $secret); } else { $this->config->setUserValue($userId, 'spreed', 'signaling_ticket_secret', $secret); } @@ -741,7 +742,7 @@ private function getSignalingTicketV1(?string $userId): string { } private function ensureSignalingTokenKeys(string $alg): void { - $secret = $this->config->getAppValue('spreed', 'signaling_token_privkey_' . strtolower($alg)); + $secret = $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($alg)); if ($secret) { return; } @@ -775,12 +776,12 @@ private function ensureSignalingTokenKeys(string $alg): void { throw new \Exception('Unsupported algorithm ' . $alg); } - $this->config->setAppValue('spreed', 'signaling_token_privkey_' . strtolower($alg), $secret); - $this->config->setAppValue('spreed', 'signaling_token_pubkey_' . strtolower($alg), $public); + $this->appConfig->setAppValueString('signaling_token_privkey_' . strtolower($alg), $secret); + $this->appConfig->setAppValueString('signaling_token_pubkey_' . strtolower($alg), $public); } public function getSignalingTokenAlgorithm(): string { - return $this->config->getAppValue('spreed', 'signaling_token_alg', 'ES256'); + return $this->appConfig->getAppValueString(self::SIGNALING_TOKEN_ALG); } public function getSignalingTokenPrivateKey(?string $alg = null): string { @@ -789,7 +790,7 @@ public function getSignalingTokenPrivateKey(?string $alg = null): string { } $this->ensureSignalingTokenKeys($alg); - return $this->config->getAppValue('spreed', 'signaling_token_privkey_' . strtolower($alg)); + return $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($alg)); } public function getSignalingTokenPublicKey(?string $alg = null): string { @@ -798,7 +799,7 @@ public function getSignalingTokenPublicKey(?string $alg = null): string { } $this->ensureSignalingTokenKeys($alg); - return $this->config->getAppValue('spreed', 'signaling_token_pubkey_' . strtolower($alg)); + return $this->appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($alg)); } public function deriveSignalingTokenPublicKey(#[SensitiveParameter] string $privateKey, string $alg): string { @@ -895,7 +896,7 @@ private function getSignalingTicketV2(?string $userId, ?string $cloudId): string */ public function validateSignalingTicket(?string $userId, #[SensitiveParameter] string $ticket): bool { if (empty($userId)) { - $secret = $this->config->getAppValue('spreed', 'signaling_ticket_secret'); + $secret = $this->appConfig->getAppValueString(self::SIGNALING_TICKET_SECRET); } else { $secret = $this->config->getUserValue($userId, 'spreed', 'signaling_ticket_secret'); } diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php index 964820f6350..d5367ee8324 100644 --- a/lib/ConfigLexicon.php +++ b/lib/ConfigLexicon.php @@ -150,6 +150,9 @@ public function getAppConfigs(): array { new Entry(UserPreference::CHAT_STYLE, ValueType::STRING, UserPreference::CHAT_STYLE_SPLIT), new Entry(SignalingManager::HAS_FEATURE_CHANGED_USERS, ValueType::BOOL, false), new Entry(Config::RETENTION_CLASSIFIED_ROOMS, ValueType::INT, 3600, definition: 'Retention period of classified conversations in seconds after a call happened (`0` means no-retention)'), + new Entry(Config::RETENTION_EVENT_ROOMS, ValueType::INT, 28, definition: 'Retention period of event conversations in days (`0` means no-retention)'), + new Entry(Config::RETENTION_PHONE_ROOMS, ValueType::INT, 7, definition: 'Retention period of phone dial-in and dial-out conversations in days (`0` means no-retention'), + new Entry(Config::RETENTION_INSTANT_MEETINGS, ValueType::INT, 1, definition: 'Retention period of instant meetings in days (`0` means no-retention)'), new Entry(Config::STUN_SERVERS, ValueType::ARRAY, [Config::DEFAULT_STUN_SERVER], definition: 'List of STUN servers for WebRTC connections', flags: IAppConfig::FLAG_SENSITIVE), new Entry(Config::TURN_SERVERS, ValueType::ARRAY, [], definition: 'List of TURN servers for WebRTC connections', flags: IAppConfig::FLAG_SENSITIVE), new Entry(Config::ALLOWED_GROUPS_TALK, ValueType::ARRAY, [], definition: 'List of group ids that are allowed to use Talk'), @@ -160,6 +163,8 @@ public function getAppConfigs(): array { new Entry(Config::FEDERATION_INCOMING_ENABLED, ValueType::BOOL, true, definition: 'Whether users of this instance can be invited to federated conversations'), new Entry(Config::FEDERATION_OUTGOING_ENABLED, ValueType::BOOL, true, definition: 'Whether users of this instance can invite federated users into conversations'), new Entry(Config::FEDERATION_ONLY_TRUSTED_SERVERS, ValueType::BOOL, false, definition: 'Whether federation should be limited to the list of "Trusted servers"'), + new Entry(Config::ALLOWED_START_CALLS, ValueType::INT, 0, definition: 'Who can start a call,' . PHP_EOL . 'see https://github.com/nextcloud/spreed/blob/main/docs/constants.md#start-call'), + new Entry(Config::ALLOWED_START_CALLS_GROUPS, ValueType::ARRAY, [], definition: 'List of group ids that are allowed to start calls (everyone when empty). This also applies to moderators; guests and federated users can then never start calls.' . PHP_EOL . 'For federated conversations the host server decides. Others can still chat and join ongoing calls'), new Entry(Config::BREAKOUT_ROOMS_ENABLED, ValueType::BOOL, true, definition: 'Whether or not breakout rooms are allowed (Will only prevent creating new breakout rooms. Existing conversations are not modified.'), new Entry(Config::CONVERSATIONS_FILES, ValueType::BOOL, true, definition: 'Whether the files app integration is enabled allowing tostart conversations in the right sidebar'), new Entry(Config::CONVERSATIONS_FILES_PUBLIC_SHARES, ValueType::BOOL, true, definition: 'Whether the public share integration is enabled allowing to start conversations in the right sidebar on the public share page (Requires `conversations_files` also to be enabled'), @@ -193,6 +198,7 @@ public function getAppConfigs(): array { new Entry(Config::BACKGROUNDS_DEFAULT_FOR_USERS, ValueType::BOOL, definition: 'Whether users are allowed to use the default virutal backgrounds provided by the releases'), new Entry(Config::BACKGROUNDS_UPLOAD_USERS, ValueType::BOOL, definition: 'Whether users are allowed to upload custom virtual backgrounds and choose from their Nextcloud Files'), new Entry(Config::CREATE_SAMPLES, ValueType::BOOL, true, definition: 'Create sample conversations (the content can be overwritten by providing files in a provided `samples_directory` app config)'), + new Entry(Config::SAMPLES_DIRECTORY, ValueType::STRING, '', definition: 'Specify a readable directory that contains other sample conversation data'), new Entry(Config::MATTERBRIDGE_ENABLED, ValueType::BOOL, false, definition: 'Whether the Matterbridge integration is enabled and can be configured'), new Entry(Config::MATRIX_ENABLED, ValueType::BOOL, false, definition: 'Whether users can link a Matrix account and use their Matrix rooms as conversations'), new Entry(Config::MATRIX_ALLOWED_GROUPS, ValueType::ARRAY, [], definition: 'List of group ids that are allowed to link a Matrix account (empty means everyone)'), @@ -225,6 +231,10 @@ public function getAppConfigs(): array { 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_BRIDGE_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured', rename: 'sip_dialout'), + new Entry(Config::SIGNALING_TICKET_SECRET, ValueType::STRING, '', definition: 'Secret used to secure the signaling tickets for guests (255 character random string)', flags: IAppConfig::FLAG_SENSITIVE), + new Entry(Config::SIGNALING_TOKEN_ALG, ValueType::STRING, 'ES256', definition: 'Algorithm for the signaling tickets'), + new Entry(Config::SIGNALING_SERVERS, ValueType::ARRAY, ['servers' => [],'secret' => ''], definition: 'List of signaling servers, should be configured via the web interface or the OCC commands', flags: IAppConfig::FLAG_SENSITIVE), + new Entry(Config::SIGNALING_SERVERS_SECRET, ValueType::STRING, '', flags: IAppConfig::FLAG_SENSITIVE), ]; } diff --git a/lib/Controller/HostedSignalingServerController.php b/lib/Controller/HostedSignalingServerController.php index 20db83f4afe..aef0fc41091 100644 --- a/lib/Controller/HostedSignalingServerController.php +++ b/lib/Controller/HostedSignalingServerController.php @@ -23,7 +23,6 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\AppFramework\Services\IAppConfig; -use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use Psr\Log\LoggerInterface; @@ -34,7 +33,6 @@ public function __construct( string $appName, IRequest $request, private readonly IL10N $l10n, - private readonly IConfig $config, private readonly IAppConfig $appConfig, private readonly LoggerInterface $logger, private readonly HostedSignalingServerService $hostedSignalingServerService, @@ -154,9 +152,11 @@ public function deleteAccount(): DataResponse { $this->appConfig->deleteAppValue(Config::HOSTED_SIGNALING_SERVER_ACCOUNT); $this->appConfig->deleteAppValue(Config::HOSTED_SIGNALING_SERVER_ACCOUNT_ID); + $this->appConfig->deleteAppValue(Config::HOSTED_SIGNALING_SERVER_NONCE); // remove signaling servers if account is not active anymore - $this->config->deleteAppValue('spreed', 'signaling_servers'); + $this->appConfig->deleteAppValue(Config::SIGNALING_SERVERS); + $this->appConfig->deleteAppValue(Config::SIGNALING_SERVERS_SECRET); $this->logger->info('Deleted hosted signaling server account with ID ' . $accountId); diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index c23961bdadf..d2721066bfe 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -192,16 +192,16 @@ protected function getTalkHashHeader(): array { $this->config->getAppValue('spreed', 'installed_version'), json_encode($this->appConfig->getAppValueArray(Config::STUN_SERVERS)), json_encode($this->appConfig->getAppValueArray(Config::TURN_SERVERS)), - $this->config->getAppValue('spreed', 'signaling_servers'), - $this->config->getAppValue('spreed', 'signaling_ticket_secret'), - $this->config->getAppValue('spreed', 'signaling_token_alg', 'ES256'), - $this->config->getAppValue('spreed', 'signaling_token_privkey_' . $this->config->getAppValue('spreed', 'signaling_token_alg', 'ES256')), - $this->config->getAppValue('spreed', 'signaling_token_pubkey_' . $this->config->getAppValue('spreed', 'signaling_token_alg', 'ES256')), + json_encode($this->appConfig->getAppValueArray(Config::SIGNALING_SERVERS)), + $this->appConfig->getAppValueString(Config::SIGNALING_TICKET_SECRET), + $this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG), + $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG))), + $this->appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG))), $this->appConfig->getAppValueBool(Config::CALL_RECORDING), json_encode($this->appConfig->getAppValueArray(Config::RECORDING_SERVERS)), json_encode($this->appConfig->getAppValueArray(Config::ALLOWED_GROUPS_TALK)), $this->appConfig->getAppValueInt(Config::ALLOWED_START_CALLS), - $this->config->getAppValue('spreed', 'start_calls_groups'), + json_encode($this->appConfig->getAppValueArray(Config::ALLOWED_START_CALLS_GROUPS)), json_encode($this->appConfig->getAppValueArray(Config::ALLOWED_GROUPS_CONVERSATIONS)), $this->appConfig->getAppValueInt(Config::DEFAULT_ROOM_PERMISSIONS), $this->appConfig->getAppValueBool(Config::BREAKOUT_ROOMS_ENABLED), diff --git a/lib/Listener/GroupDeletedListener.php b/lib/Listener/GroupDeletedListener.php index b2f26d81e9b..919352700d4 100644 --- a/lib/Listener/GroupDeletedListener.php +++ b/lib/Listener/GroupDeletedListener.php @@ -41,7 +41,7 @@ public function handle(Event $event): void { $gid = $event->getGroup()->getGID(); $this->removeGroupFromConfig(Config::ALLOWED_GROUPS_SIP, $gid); - $this->removeGroupFromConfig('start_calls_groups', $gid); + $this->removeGroupFromConfig(Config::ALLOWED_START_CALLS_GROUPS, $gid); $this->removeGroupFromConfig(Config::ALLOWED_GROUPS_CONVERSATIONS, $gid); $this->removeGroupFromConfig(Config::ALLOWED_GROUPS_TALK, $gid); diff --git a/lib/Migration/Version2000Date20171026140257.php b/lib/Migration/Version2000Date20171026140257.php index c12b8840ec9..6da95b8c2f3 100644 --- a/lib/Migration/Version2000Date20171026140257.php +++ b/lib/Migration/Version2000Date20171026140257.php @@ -8,6 +8,8 @@ namespace OCA\Talk\Migration; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; @@ -25,6 +27,7 @@ class Version2000Date20171026140257 extends SimpleMigrationStep { public function __construct( private readonly IDBConnection $connection, private readonly IConfig $config, + private readonly IAppConfig $appConfig, private readonly ISecureRandom $secureRandom, ) { $this->tokens = []; @@ -44,7 +47,7 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array } $chars = str_replace(['l', '0', '1'], '', ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS); - $entropy = (int)$this->config->getAppValue('spreed', 'token_entropy', '8'); + $entropy = $this->appConfig->getAppValueInt(Config::TOKEN_ENTROPY); $update = $this->connection->getQueryBuilder(); $update->update('spreedme_rooms') diff --git a/lib/Migration/Version23000Date20251114105144.php b/lib/Migration/Version23000Date20251114105144.php index e3a4d7380a5..f3ae485103e 100644 --- a/lib/Migration/Version23000Date20251114105144.php +++ b/lib/Migration/Version23000Date20251114105144.php @@ -10,6 +10,7 @@ namespace OCA\Talk\Migration; use Closure; +use OCA\Talk\Config; use OCA\Talk\Participant; use OCP\AppFramework\Services\IAppConfig; use OCP\Migration\Attributes\DataCleansing; @@ -30,10 +31,10 @@ public function __construct( #[Override] public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { // Persist the previous default for group notifications for installations on update. - $previous = $this->appConfig->getAppValueInt('default_group_notification', Participant::NOTIFY_DEFAULT); + $previous = $this->appConfig->getAppValueInt(Config::DEFAULT_GROUP_NOTIFICATION, Participant::NOTIFY_DEFAULT); if ($previous === Participant::NOTIFY_DEFAULT) { $this->appConfig->setAppValueInt( - 'default_group_notification', + Config::DEFAULT_GROUP_NOTIFICATION, Participant::NOTIFY_MENTION, ); } diff --git a/lib/Participant.php b/lib/Participant.php index d21b1f9af10..7fbd6a418b5 100644 --- a/lib/Participant.php +++ b/lib/Participant.php @@ -181,7 +181,7 @@ public function canStartCall(IAppConfig $appConfig, IGroupManager $groupManager) } protected function isAllowedToStartCallByGroup(IAppConfig $appConfig, IGroupManager $groupManager): bool { - $allowedGroups = $appConfig->getAppValueArray('start_calls_groups'); + $allowedGroups = $appConfig->getAppValueArray(Config::ALLOWED_START_CALLS_GROUPS); if (empty($allowedGroups)) { return true; } diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php index 2900e7a9fbd..83e237c7ccb 100644 --- a/lib/Settings/Admin/AdminSettings.php +++ b/lib/Settings/Admin/AdminSettings.php @@ -78,7 +78,7 @@ protected function initGeneralSettings(): void { protected function initAllowedGroups(): void { $this->initialState->provideInitialState('start_calls', $this->appConfig->getAppValueInt(Config::ALLOWED_START_CALLS)); - $groups = $this->getGroupDetailsArray($this->appConfig->getAppValueArray('start_calls_groups'), 'start_calls_groups'); + $groups = $this->getGroupDetailsArray($this->appConfig->getAppValueArray(Config::ALLOWED_START_CALLS_GROUPS), 'start_calls_groups'); $this->initialState->provideInitialState('start_calls_groups', $groups); $groups = $this->getGroupDetailsArray($this->talkConfig->getAllowedConversationsGroupIds(), 'start_conversations'); diff --git a/tests/php/CapabilitiesTest.php b/tests/php/CapabilitiesTest.php index ddfd7a6b2a7..fcb67b9bc70 100644 --- a/tests/php/CapabilitiesTest.php +++ b/tests/php/CapabilitiesTest.php @@ -389,11 +389,11 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea ['core', 'backgroundjobs_mode', 'ajax', 'cron'], ]); - $this->appConfig->expects($this->any()) - ->method('getAppValueBool') + $this->appConfig->method('getAppValueBool') ->willReturnMap([ - ['backgrounds_default_for_users', true, true], - ['backgrounds_upload_users', true, true], + ['backgrounds_branded_for_guests', false], + ['backgrounds_default_for_users', true], + ['backgrounds_upload_users', true], ['sip_bridge_dialout', false], ['sip_bridge_dialout_anonymous', false], ['enable_matterbridge', false], @@ -401,9 +401,6 @@ public function testGetCapabilitiesUserAllowed(bool $isNotAllowed, bool $canCrea ['federation_incoming_enabled', true], ['federation_outgoing_enabled', true], ['federation_only_trusted_servers', false], - ['backgrounds_branded_for_guests', false], - ['backgrounds_default_for_users', true], - ['backgrounds_upload_users', true], ]); $this->appConfig->expects($this->any()) diff --git a/tests/php/Chat/NotifierTest.php b/tests/php/Chat/NotifierTest.php index 11ede3d42c9..c6a87195a33 100644 --- a/tests/php/Chat/NotifierTest.php +++ b/tests/php/Chat/NotifierTest.php @@ -73,7 +73,6 @@ protected function getNotifier(array $methods = []) { $this->groupManager, $this->participantService, $this->threadService, - $this->config, $this->appConfig, $this->timeFactory, $this->util, @@ -87,7 +86,6 @@ protected function getNotifier(array $methods = []) { $this->groupManager, $this->participantService, $this->threadService, - $this->config, $this->appConfig, $this->timeFactory, $this->util diff --git a/tests/php/Command/Signaling/AddTest.php b/tests/php/Command/Signaling/AddTest.php index ff88a9cc49e..bd1e80b801f 100644 --- a/tests/php/Command/Signaling/AddTest.php +++ b/tests/php/Command/Signaling/AddTest.php @@ -9,14 +9,15 @@ namespace OCA\Talk\Tests\php\Command\Signaling; use OCA\Talk\Command\Signaling\Add; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class AddTest extends TestCase { - protected IConfig&MockObject $config; + protected IAppConfig&MockObject $appConfig; protected InputInterface&MockObject $input; protected OutputInterface&MockObject $output; protected Add $command; @@ -24,9 +25,9 @@ class AddTest extends TestCase { public function setUp(): void { parent::setUp(); - $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); - $this->command = new Add($this->config); + $this->command = new Add($this->appConfig); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); @@ -48,7 +49,7 @@ public function testServerEmptyString(): void { $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('Server cannot be empty.')); - $this->config->expects($this->never()) + $this->appConfig->expects($this->never()) ->method('setAppValue'); self::invokePrivate($this->command, 'execute', [$this->input, $this->output]); @@ -70,7 +71,7 @@ public function testSecretEmptyString(): void { $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('Secret cannot be empty.')); - $this->config->expects($this->never()) + $this->appConfig->expects($this->never()) ->method('setAppValue'); self::invokePrivate($this->command, 'execute', [$this->input, $this->output]); @@ -89,25 +90,13 @@ public function testAddServerToEmptyList(): void { $this->input->method('getOption') ->with('verify') ->willReturn(true); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([])); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('spreed'), - $this->equalTo('signaling_servers'), - $this->equalTo(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling.test.com', - 'verify' => true - ] - ], - 'secret' => 'my-test-secret' - ])) - ); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn([]); + $this->appConfig->expects($this->once()) + ->method('setAppValueArray') + ->with(Config::SIGNALING_SERVERS, ['servers' => [['server' => 'wss://signaling.test.com', 'verify' => true]],'secret' => 'my-test-secret']); $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('Added signaling server wss://signaling.test.com.')); @@ -128,37 +117,13 @@ public function testAddServerToNonEmptyList(): void { $this->input->method('getOption') ->with('verify') ->willReturn(true); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => true - ] - ], - 'secret' => 'my-test-secret' - ])); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('spreed'), - $this->equalTo('signaling_servers'), - $this->equalTo(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => true - ], - [ - 'server' => 'wss://signaling2.test.com', - 'verify' => true - ] - ], - 'secret' => 'my-test-secret' - ])) - ); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn(['servers' => [['server' => 'wss://signaling1.test.com','verify' => true]],'secret' => 'my-test-secret']); + $this->appConfig->expects($this->once()) + ->method('setAppValueArray') + ->with(Config::SIGNALING_SERVERS, ['servers' => [['server' => 'wss://signaling1.test.com','verify' => true],['server' => 'wss://signaling2.test.com','verify' => true]],'secret' => 'my-test-secret']); $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('Added signaling server wss://signaling2.test.com.')); diff --git a/tests/php/Command/Signaling/DeleteTest.php b/tests/php/Command/Signaling/DeleteTest.php index ce76771f9b3..c75b01bea67 100644 --- a/tests/php/Command/Signaling/DeleteTest.php +++ b/tests/php/Command/Signaling/DeleteTest.php @@ -9,14 +9,15 @@ namespace OCA\Talk\Tests\php\Command\Signaling; use OCA\Talk\Command\Signaling\Delete; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class DeleteTest extends TestCase { - protected IConfig&MockObject $config; + protected IAppConfig&MockObject $appConfig; protected InputInterface&MockObject $input; protected OutputInterface&MockObject $output; protected Delete $command; @@ -24,9 +25,9 @@ class DeleteTest extends TestCase { public function setUp(): void { parent::setUp(); - $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); - $this->command = new Delete($this->config); + $this->command = new Delete($this->appConfig); $this->input = $this->createMock(InputInterface::class); $this->output = $this->createMock(OutputInterface::class); @@ -36,20 +37,13 @@ public function testDeleteIfEmpty(): void { $this->input->method('getArgument') ->with('server') ->willReturn('wss://signaling.example.com'); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(''); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('spreed'), - $this->equalTo('signaling_servers'), - $this->equalTo(json_encode([ - 'servers' => [], - 'secret' => '' - ])) - ); + $this->appConfig->expects($this->any()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn([]); + $this->appConfig->expects($this->once()) + ->method('setAppValueArray') + ->with(Config::SIGNALING_SERVERS, ['servers' => [],'secret' => '']); $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('There is nothing to delete.')); @@ -61,45 +55,13 @@ public function testDelete(): void { $this->input->method('getArgument') ->with('server') ->willReturn('wss://signaling2.test.com'); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => false, - ], - [ - 'server' => 'wss://signaling2.test.com', - 'verify' => false, - ], - [ - 'server' => 'wss://signaling3.test.com', - 'verify' => false, - ] - ], - 'secret' => 'my-test-secret', - ])); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('spreed'), - $this->equalTo('signaling_servers'), - $this->equalTo(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => false, - ], - [ - 'server' => 'wss://signaling3.test.com', - 'verify' => false, - ] - ], - 'secret' => 'my-test-secret', - ])) - ); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn(['servers' => [['server' => 'wss://signaling1.test.com','verify' => false],['server' => 'wss://signaling2.test.com','verify' => false],['server' => 'wss://signaling3.test.com','verify' => false]],'secret' => 'my-test-secret']); + $this->appConfig->expects($this->once()) + ->method('setAppValueArray') + ->with(Config::SIGNALING_SERVERS, ['servers' => [['server' => 'wss://signaling1.test.com','verify' => false],['server' => 'wss://signaling3.test.com','verify' => false]],'secret' => 'my-test-secret']); $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('Deleted wss://signaling2.test.com.')); @@ -111,33 +73,13 @@ public function testNothingToDelete(): void { $this->input->method('getArgument') ->with('server') ->willReturn('wss://signaling4.test.com'); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => false, - ] - ], - 'secret' => 'my-test-secret', - ])); - $this->config->expects($this->once()) - ->method('setAppValue') - ->with( - $this->equalTo('spreed'), - $this->equalTo('signaling_servers'), - $this->equalTo(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling1.test.com', - 'verify' => false, - ] - ], - 'secret' => 'my-test-secret', - ])) - ); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn(['servers' => [['server' => 'wss://signaling1.test.com','verify' => false]],'secret' => 'my-test-secret']); + $this->appConfig->expects($this->once()) + ->method('setAppValueArray') + ->with(Config::SIGNALING_SERVERS, ['servers' => [['server' => 'wss://signaling1.test.com','verify' => false]],'secret' => 'my-test-secret']); $this->output->expects($this->once()) ->method('writeln') ->with($this->equalTo('There is nothing to delete.')); diff --git a/tests/php/Command/Signaling/ListCommandTest.php b/tests/php/Command/Signaling/ListCommandTest.php index 64b8958e0cc..18bbe9e607c 100644 --- a/tests/php/Command/Signaling/ListCommandTest.php +++ b/tests/php/Command/Signaling/ListCommandTest.php @@ -9,14 +9,15 @@ namespace OCA\Talk\Tests\php\Command\Signaling; use OCA\Talk\Command\Signaling\ListCommand; -use OCP\IConfig; +use OCA\Talk\Config; +use OCP\AppFramework\Services\IAppConfig; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; class ListCommandTest extends TestCase { - protected IConfig&MockObject $config; + protected IAppConfig&MockObject $appConfig; protected InputInterface&MockObject $input; protected OutputInterface&MockObject $output; protected ListCommand&MockObject $command; @@ -24,10 +25,10 @@ class ListCommandTest extends TestCase { public function setUp(): void { parent::setUp(); - $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->command = $this->getMockBuilder(ListCommand::class) - ->setConstructorArgs([$this->config]) + ->setConstructorArgs([$this->appConfig]) ->onlyMethods(['writeMixedInOutputFormat']) ->getMock(); @@ -36,10 +37,10 @@ public function setUp(): void { } public function testEmptyAppConfig(): void { - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([])); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn([]); $this->command->expects($this->once()) ->method('writeMixedInOutputFormat') @@ -53,18 +54,10 @@ public function testEmptyAppConfig(): void { } public function testAppConfigDataChanges(): void { - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('spreed', 'signaling_servers') - ->willReturn(json_encode([ - 'servers' => [ - [ - 'server' => 'wss://signaling.example.com', - 'verify' => true - ] - ], - 'secret' => 'my-test-secret' - ])); + $this->appConfig->expects($this->once()) + ->method('getAppValueArray') + ->with(Config::SIGNALING_SERVERS) + ->willReturn(['servers' => [['server' => 'wss://signaling.example.com','verify' => true]],'secret' => 'my-test-secret']); $this->command->expects($this->once()) ->method('writeMixedInOutputFormat') diff --git a/tests/php/ConfigTest.php b/tests/php/ConfigTest.php index de932dbb3b9..d968409f0da 100644 --- a/tests/php/ConfigTest.php +++ b/tests/php/ConfigTest.php @@ -8,6 +8,7 @@ namespace OCA\Talk\Tests\php; +use OC\AppFramework\Services\AppConfig; use OCA\Talk\Config; use OCA\Talk\Events\BeforeTurnServersGetEvent; use OCA\Talk\Tests\php\Mocks\GetTurnServerListener; @@ -30,7 +31,7 @@ class ConfigTest extends TestCase { protected IConfig $config; - protected IAppConfig&MockObject $appConfig; + protected IAppConfig $appConfig; protected IUserConfig&MockObject $userConfig; protected ISecureRandom&MockObject $secureRandom; protected IGroupManager&MockObject $groupManager; @@ -54,10 +55,10 @@ public function setUp(): void { $this->filenameValidator = $this->createMock(IFilenameValidator::class); } - protected function getConfig(): Config { + protected function getConfig(?IAppConfig $appConfig = null): Config { return new Config( $this->config, - $this->appConfig, + $appConfig ?? $this->appConfig, $this->userConfig, $this->secureRandom, $this->groupManager, @@ -69,6 +70,18 @@ protected function getConfig(): Config { ); } + protected function getAppConfig(): IAppConfig { + return $this->appConfig; + } + + protected function getRealAppConfig(): AppConfig { + return new AppConfig( + \OCP\Server::get(IConfig::class), + \OCP\Server::get(\OCP\IAppConfig::class), + 'spreed', + ); + } + public function testGetStunServers(): void { $servers = [ 'stun1.example.com:443', @@ -334,7 +347,7 @@ public static function dataTicketV2Algorithm(): array { #[DataProvider('dataTicketV2Algorithm')] public function testSignalingTicketV2User(string $algo): void { - $this->config = \OCP\Server::get(IConfig::class); + $appConfig = $this->getRealAppConfig(); /** @var IUser&MockObject $user */ $user = $this->createMock(IUser::class); @@ -363,16 +376,17 @@ public function testSignalingTicketV2User(string $algo): void { ->method('getDisplayName') ->willReturn('Jane Doe'); - $helper = $this->getConfig(); + $helper = $this->getConfig($appConfig); + + $appConfig->setAppValueString(Config::SIGNALING_TOKEN_ALG, $algo); - $this->config->setAppValue('spreed', 'signaling_token_alg', $algo); // Make sure new keys are generated. - $this->config->deleteAppValue('spreed', 'signaling_token_privkey_' . strtolower($algo)); - $this->config->deleteAppValue('spreed', 'signaling_token_pubkey_' . strtolower($algo)); + $appConfig->deleteAppValue('signaling_token_privkey_' . strtolower($algo)); + $appConfig->deleteAppValue('signaling_token_pubkey_' . strtolower($algo)); $ticket = $helper->getSignalingTicket(Config::SIGNALING_TICKET_V2, 'user1'); $this->assertNotNull($ticket); - $key = new Key($this->config->getAppValue('spreed', 'signaling_token_pubkey_' . strtolower($algo)), $algo); + $key = new Key($appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($algo)), $algo); $decoded = JWT::decode($ticket, $key); $this->assertEquals($now, $decoded->iat); @@ -383,7 +397,7 @@ public function testSignalingTicketV2User(string $algo): void { #[DataProvider('dataTicketV2Algorithm')] public function testSignalingTicketV2Anonymous(string $algo): void { - $this->config = \OCP\Server::get(IConfig::class); + $appConfig = $this->getRealAppConfig(); $now = time(); $this->timeFactory @@ -396,16 +410,16 @@ public function testSignalingTicketV2Anonymous(string $algo): void { ->with('') ->willReturn('https://domain.invalid/nextcloud'); - $helper = $this->getConfig(); + $helper = $this->getConfig($appConfig); - $this->config->setAppValue('spreed', 'signaling_token_alg', $algo); + $appConfig->setAppValueString(Config::SIGNALING_TOKEN_ALG, $algo); // Make sure new keys are generated. - $this->config->deleteAppValue('spreed', 'signaling_token_privkey_' . strtolower($algo)); - $this->config->deleteAppValue('spreed', 'signaling_token_pubkey_' . strtolower($algo)); + $appConfig->deleteAppValue('signaling_token_privkey_' . strtolower($algo)); + $appConfig->deleteAppValue('signaling_token_pubkey_' . strtolower($algo)); $ticket = $helper->getSignalingTicket(Config::SIGNALING_TICKET_V2, null); $this->assertNotNull($ticket); - $key = new Key($this->config->getAppValue('spreed', 'signaling_token_pubkey_' . strtolower($algo)), $algo); + $key = new Key($appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($algo)), $algo); $decoded = JWT::decode($ticket, $key); $this->assertEquals($now, $decoded->iat); diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index 34a05478182..a356088cc5d 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -8,6 +8,7 @@ namespace OCA\Talk\Tests\php\Controller; +use OC\AppFramework\Services\AppConfig; use OCA\Talk\Authenticator; use OCA\Talk\Chat\CommentsManager; use OCA\Talk\Config; @@ -88,29 +89,28 @@ class SignalingControllerTest extends TestCase { protected IDBConnection $dbConnection; protected IConfig $serverConfig; protected ?Config $config = null; - protected IAppConfig&MockObject $appConfig; + protected IAppConfig $appConfig; protected ?string $userId = null; protected ?ISecureRandom $secureRandom = null; protected ?IEventDispatcher $dispatcher = null; private ?CustomInputSignalingController $controller = null; + private const string SIP_BRIDGE_SECRET = 'MySIPSecretValueMySIPSecretValue1234'; + private const string SIGNALING_SECRET = 'MySecretValueMySecretValue1234567890'; + public function setUp(): void { parent::setUp(); $this->userId = 'testUser'; $this->secureRandom = \OCP\Server::get(ISecureRandom::class); $this->request = $this->createMock(IRequest::class); - /** @var MockObject|IAppConfig $appConfig */ - $this->appConfig = $this->createMock(IAppConfig::class); $timeFactory = $this->createMock(ITimeFactory::class); $groupManager = $this->createMock(IGroupManager::class); $this->serverConfig = \OCP\Server::get(IConfig::class); - $this->serverConfig->setAppValue('spreed', 'signaling_servers', json_encode([ - 'secret' => 'MySecretValueMySecretValue1234567890', - ])); - $this->serverConfig->setAppValue('spreed', 'signaling_ticket_secret', 'the-app-ticket-secret'); + $this->appConfig = $this->getRealAppConfig(); $this->serverConfig->setUserValue($this->userId, 'spreed', 'signaling_ticket_secret', 'the-user-ticket-secret'); + $this->appConfig->setAppValueArray(Config::SIGNALING_SERVERS, ['servers' => [], 'secret' => self::SIGNALING_SECRET]); $this->userManager = $this->createMock(IUserManager::class); $this->dispatcher = \OCP\Server::get(IEventDispatcher::class); $urlGenerator = $this->createMock(IURLGenerator::class); @@ -133,6 +133,18 @@ public function setUp(): void { $this->recreateSignalingController(); } + protected function getAppConfig(): IAppConfig { + return $this->appConfig; + } + + protected function getRealAppConfig(): AppConfig { + return new AppConfig( + \OCP\Server::get(IConfig::class), + \OCP\Server::get(\OCP\IAppConfig::class), + 'spreed', + ); + } + private function recreateSignalingController() { $this->controller = new CustomInputSignalingController( 'spreed', @@ -554,7 +566,11 @@ private function validateBackendRandom($data, $random, $checksum) { if (empty($checksum)) { return false; } - $hash = hash_hmac('sha256', $random . $data, $this->config->getSignalingSecret()); + + $this->appConfig->setAppValueString('signaling_servers_secret', 'MySecretValueMySecretValue1234567890'); + $signalingSecret = $this->appConfig->getAppValueString('signaling_servers_secret'); + + $hash = hash_hmac('sha256', $random . $data, $signalingSecret); return hash_equals($hash, strtolower((string)$checksum)); } @@ -562,7 +578,10 @@ private function calculateBackendChecksum($data, $random) { if (empty($random) || strlen((string)$random) < 32) { return false; } - $hash = hash_hmac('sha256', $random . $data, $this->config->getSignalingSecret()); + + $this->appConfig->setAppValueString('signaling_servers_secret', 'MySecretValueMySecretValue1234567890'); + $signalingSecret = $this->appConfig->getAppValueString('signaling_servers_secret'); + $hash = hash_hmac('sha256', $random . $data, $signalingSecret); return $hash; } @@ -571,6 +590,8 @@ public function testBackendChecksums(): void { $data = '{"type":"auth","auth":{"version":"1.0","params":{"hello":"world"}}}'; $random = 'afb6b872ab03e3376b31bf0af601067222ff7990335ca02d327071b73c0119c6'; $checksum = '37455eb661e5a4bc81cc7e1b10beb2cf09c30d0161f82ce12afcc108dd76e4f3'; + $this->assertEquals('37455eb661e5a4bc81cc7e1b10beb2cf09c30d0161f82ce12afcc108dd76e4f3', hash_hmac('sha256', 'afb6b872ab03e3376b31bf0af601067222ff7990335ca02d327071b73c0119c6{"type":"auth","auth":{"version":"1.0","params":{"hello":"world"}}}', 'MySecretValueMySecretValue1234567890')); + $this->assertEquals('02dea65abdd2b67b751e6799711df7346c3a7ae3a3de5262bcc75074a87bcf47', hash_hmac('sha256', 'afb6b872ab03e3376b31bf0af601067222ff7990335ca02d327071b73c0119c6{"type":"auth","auth":{"version":"1.0","params":{"hello":"world"}}}', '')); $this->assertEquals($checksum, $this->calculateBackendChecksum($data, $random)); $this->assertTrue($this->validateBackendRandom($data, $random, $checksum)); } @@ -1371,12 +1392,13 @@ public function testLeaveRoomWithOldSession(): void { $dispatcher = \OCP\Server::get(IEventDispatcher::class); /** @var ParticipantService $participantService */ $participantService = \OCP\Server::get(ParticipantService::class); + $appConfig = $this->getRealAppConfig(); $this->manager = new Manager( $dbConnection, \OCP\Server::get(IConfig::class), $this->createMock(Config::class), - $this->createMock(IAppConfig::class), + $appConfig, \OCP\Server::get(IAppManager::class), \OCP\Server::get(AttendeeMapper::class), \OCP\Server::get(SessionMapper::class), @@ -1455,8 +1477,6 @@ public function testLeaveRoomWithOldSession(): void { $this->assertEquals($newSessionId, $participant->getSession()->getSessionId()); } - private const string SIP_BRIDGE_SECRET = 'MySIPSecretValueMySIPSecretValue1234'; - private function sipBridgeChecksum(string $data, string $random): string { return hash_hmac('sha256', $random . $data, self::SIP_BRIDGE_SECRET); } diff --git a/tests/php/ParticipantTest.php b/tests/php/ParticipantTest.php index bcb1bba9651..03721112365 100644 --- a/tests/php/ParticipantTest.php +++ b/tests/php/ParticipantTest.php @@ -61,6 +61,10 @@ public function testCanStartCallWithGroupRestriction( ->with(Config::ALLOWED_START_CALLS) ->willReturn(Room::START_CALL_EVERYONE); + $appConfig->expects($this->once()) + ->method('getAppValueInt') + ->with('start_calls') + ->willReturn(Room::START_CALL_EVERYONE); $appConfig->expects($this->once()) ->method('getAppValueArray') ->with('start_calls_groups') @@ -93,6 +97,12 @@ protected function createConfig(int $startCalls = Room::START_CALL_EVERYONE): IC return $config; } + protected function createAppConfig(int $startCalls = Room::START_CALL_EVERYONE): IAppConfig&MockObject { + $appConfig = $this->createMock(IAppConfig::class); + $appConfig->method('getAppValueInt')->with('start_calls')->willReturn($startCalls); + return $appConfig; + } + public function testChannelRemovesCallPermissionsFromModerators(): void { $participant = $this->createParticipant(true, Participant::MODERATOR, Attendee::PERMISSIONS_DEFAULT); $permissions = $participant->getPermissions(); @@ -124,17 +134,17 @@ public function testNonChannelKeepsCallPermissions(): void { public function testCanStartCallIsFalseInChannelForModerators(): void { $participant = $this->createParticipant(true, Participant::MODERATOR, Attendee::PERMISSIONS_DEFAULT); - $this->assertFalse($participant->canStartCall($this->createMock(IAppConfig::class), $this->createMock(IGroupManager::class))); + $this->assertFalse($participant->canStartCall($this->createAppConfig(), $this->createMock(IGroupManager::class))); } public function testCanStartCallIsFalseInChannelForUsers(): void { $participant = $this->createParticipant(true, Participant::USER, Attendee::PERMISSIONS_DEFAULT); - $this->assertFalse($participant->canStartCall($this->createMock(IAppConfig::class), $this->createMock(IGroupManager::class))); + $this->assertFalse($participant->canStartCall($this->createAppConfig(), $this->createMock(IGroupManager::class))); } public function testCanStartCallIsTrueInNonChannelForModerators(): void { $participant = $this->createParticipant(false, Participant::MODERATOR, Attendee::PERMISSIONS_DEFAULT); - $this->assertTrue($participant->canStartCall($this->createMock(IAppConfig::class), $this->createMock(IGroupManager::class))); + $this->assertTrue($participant->canStartCall($this->createAppConfig(), $this->createMock(IGroupManager::class))); } public function testIsOwner(): void {