diff options
Diffstat (limited to 'apps/settings/lib/Settings/Admin')
-rw-r--r-- | apps/settings/lib/Settings/Admin/ArtificialIntelligence.php | 218 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Delegation.php | 54 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Mail.php | 51 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/MailProvider.php | 52 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Overview.php | 47 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Security.php | 80 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Server.php | 98 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Sharing.php | 177 | ||||
-rw-r--r-- | apps/settings/lib/Settings/Admin/Users.php | 61 |
9 files changed, 493 insertions, 345 deletions
diff --git a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php new file mode 100644 index 00000000000..aaec0049b20 --- /dev/null +++ b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php @@ -0,0 +1,218 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Settings\Settings\Admin; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; +use OCP\IAppConfig; +use OCP\IL10N; +use OCP\Settings\IDelegatedSettings; +use OCP\SpeechToText\ISpeechToTextManager; +use OCP\SpeechToText\ISpeechToTextProviderWithId; +use OCP\TextProcessing\IManager; +use OCP\TextProcessing\IProvider; +use OCP\TextProcessing\IProviderWithId; +use OCP\TextProcessing\ITaskType; +use OCP\Translation\ITranslationManager; +use OCP\Translation\ITranslationProviderWithId; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerInterface; + +class ArtificialIntelligence implements IDelegatedSettings { + public function __construct( + private IAppConfig $appConfig, + private IL10N $l, + private IInitialState $initialState, + private ITranslationManager $translationManager, + private ISpeechToTextManager $sttManager, + private IManager $textProcessingManager, + private ContainerInterface $container, + private \OCP\TextToImage\IManager $text2imageManager, + private \OCP\TaskProcessing\IManager $taskProcessingManager, + private LoggerInterface $logger, + ) { + } + + /** + * @return TemplateResponse + */ + public function getForm() { + $translationProviders = []; + $translationPreferences = []; + foreach ($this->translationManager->getProviders() as $provider) { + $translationProviders[] = [ + 'class' => $provider instanceof ITranslationProviderWithId ? $provider->getId() : $provider::class, + 'name' => $provider->getName(), + ]; + $translationPreferences[] = $provider instanceof ITranslationProviderWithId ? $provider->getId() : $provider::class; + } + + $sttProviders = []; + foreach ($this->sttManager->getProviders() as $provider) { + $sttProviders[] = [ + 'class' => $provider instanceof ISpeechToTextProviderWithId ? $provider->getId() : $provider::class, + 'name' => $provider->getName(), + ]; + } + + $textProcessingProviders = []; + /** @var array<class-string<ITaskType>, string|class-string<IProvider>> $textProcessingSettings */ + $textProcessingSettings = []; + foreach ($this->textProcessingManager->getProviders() as $provider) { + $textProcessingProviders[] = [ + 'class' => $provider instanceof IProviderWithId ? $provider->getId() : $provider::class, + 'name' => $provider->getName(), + 'taskType' => $provider->getTaskType(), + ]; + if (!isset($textProcessingSettings[$provider->getTaskType()])) { + $textProcessingSettings[$provider->getTaskType()] = $provider instanceof IProviderWithId ? $provider->getId() : $provider::class; + } + } + $textProcessingTaskTypes = []; + foreach ($textProcessingSettings as $taskTypeClass => $providerClass) { + /** @var ITaskType $taskType */ + try { + $taskType = $this->container->get($taskTypeClass); + } catch (NotFoundExceptionInterface $e) { + continue; + } catch (ContainerExceptionInterface $e) { + continue; + } + $textProcessingTaskTypes[] = [ + 'class' => $taskTypeClass, + 'name' => $taskType->getName(), + 'description' => $taskType->getDescription(), + ]; + } + + $text2imageProviders = []; + foreach ($this->text2imageManager->getProviders() as $provider) { + $text2imageProviders[] = [ + 'id' => $provider->getId(), + 'name' => $provider->getName(), + ]; + } + + $taskProcessingProviders = []; + /** @var array<class-string<ITaskType>, string|class-string<IProvider>> $taskProcessingSettings */ + $taskProcessingSettings = []; + foreach ($this->taskProcessingManager->getProviders() as $provider) { + $taskProcessingProviders[] = [ + 'id' => $provider->getId(), + 'name' => $provider->getName(), + 'taskType' => $provider->getTaskTypeId(), + ]; + if (!isset($taskProcessingSettings[$provider->getTaskTypeId()])) { + $taskProcessingSettings[$provider->getTaskTypeId()] = $provider->getId(); + } + } + $taskProcessingTaskTypes = []; + $taskProcessingTypeSettings = []; + foreach ($this->taskProcessingManager->getAvailableTaskTypes(true) as $taskTypeId => $taskTypeDefinition) { + $taskProcessingTaskTypes[] = [ + 'id' => $taskTypeId, + 'name' => $taskTypeDefinition['name'], + 'description' => $taskTypeDefinition['description'], + ]; + $taskProcessingTypeSettings[$taskTypeId] = true; + } + + + $this->initialState->provideInitialState('ai-stt-providers', $sttProviders); + $this->initialState->provideInitialState('ai-translation-providers', $translationProviders); + $this->initialState->provideInitialState('ai-text-processing-providers', $textProcessingProviders); + $this->initialState->provideInitialState('ai-text-processing-task-types', $textProcessingTaskTypes); + $this->initialState->provideInitialState('ai-text2image-providers', $text2imageProviders); + $this->initialState->provideInitialState('ai-task-processing-providers', $taskProcessingProviders); + $this->initialState->provideInitialState('ai-task-processing-task-types', $taskProcessingTaskTypes); + + $settings = [ + 'ai.stt_provider' => count($sttProviders) > 0 ? $sttProviders[0]['class'] : null, + 'ai.translation_provider_preferences' => $translationPreferences, + 'ai.textprocessing_provider_preferences' => $textProcessingSettings, + 'ai.text2image_provider' => count($text2imageProviders) > 0 ? $text2imageProviders[0]['id'] : null, + 'ai.taskprocessing_provider_preferences' => $taskProcessingSettings, + 'ai.taskprocessing_type_preferences' => $taskProcessingTypeSettings, + 'ai.taskprocessing_guests' => false, + ]; + foreach ($settings as $key => $defaultValue) { + $value = $defaultValue; + $json = $this->appConfig->getValueString('core', $key, '', lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true)); + if ($json !== '') { + try { + $value = json_decode($json, true, flags: JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + $this->logger->error('Failed to get settings. JSON Error in ' . $key, ['exception' => $e]); + if ($key === 'ai.taskprocessing_type_preferences') { + $value = []; + foreach ($taskProcessingTypeSettings as $taskTypeId => $taskTypeValue) { + $value[$taskTypeId] = false; + } + $settings[$key] = $value; + } + continue; + } + + switch ($key) { + case 'ai.taskprocessing_provider_preferences': + case 'ai.taskprocessing_type_preferences': + case 'ai.textprocessing_provider_preferences': + // fill $value with $defaultValue values + $value = array_merge($defaultValue, $value); + break; + case 'ai.translation_provider_preferences': + // Only show entries from $value (saved pref list) that are in $defaultValue (enabled providers) + // and add all providers that are enabled but not in the pref list + if (!is_array($defaultValue)) { + break; + } + $value = array_values(array_unique(array_merge(array_intersect($value, $defaultValue), $defaultValue), SORT_STRING)); + break; + default: + break; + } + } + $settings[$key] = $value; + } + + $this->initialState->provideInitialState('ai-settings', $settings); + + return new TemplateResponse('settings', 'settings/admin/ai'); + } + + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() { + return 'ai'; + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * E.g.: 70 + */ + public function getPriority() { + return 10; + } + + public function getName(): ?string { + return $this->l->t('Artificial Intelligence'); + } + + public function getAuthorizedAppConfig(): array { + return [ + 'core' => ['/ai..*/'], + ]; + } +} diff --git a/apps/settings/lib/Settings/Admin/Delegation.php b/apps/settings/lib/Settings/Admin/Delegation.php index 401d5b028cc..59a26d1ac04 100644 --- a/apps/settings/lib/Settings/Admin/Delegation.php +++ b/apps/settings/lib/Settings/Admin/Delegation.php @@ -1,26 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2021 Carl Schwan <carl@carlschwan.eu> - * - * @author Carl Schwan <carl@carlschwan.eu> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Admin; use OCA\Settings\AppInfo\Application; @@ -28,33 +11,19 @@ use OCA\Settings\Service\AuthorizedGroupService; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\IGroupManager; +use OCP\IURLGenerator; use OCP\Settings\IDelegatedSettings; use OCP\Settings\IManager; use OCP\Settings\ISettings; class Delegation implements ISettings { - /** @var IManager */ - private $settingManager; - - /** @var IInitialState $initialStateService */ - private $initialStateService; - - /** @var IGroupManager $groupManager */ - private $groupManager; - - /** @var AuthorizedGroupService $authorizedGroupService */ - private $authorizedGroupService; - public function __construct( - IManager $settingManager, - IInitialState $initialStateService, - IGroupManager $groupManager, - AuthorizedGroupService $authorizedGroupService + private IManager $settingManager, + private IInitialState $initialStateService, + private IGroupManager $groupManager, + private AuthorizedGroupService $authorizedGroupService, + private IURLGenerator $urlGenerator, ) { - $this->settingManager = $settingManager; - $this->initialStateService = $initialStateService; - $this->groupManager = $groupManager; - $this->authorizedGroupService = $authorizedGroupService; } /** @@ -85,9 +54,11 @@ class Delegation implements ISettings { $settings = array_merge( $settings, array_map(function (IDelegatedSettings $setting) use ($section) { + $sectionName = $section->getName() . ($setting->getName() !== null ? ' - ' . $setting->getName() : ''); return [ 'class' => get_class($setting), - 'sectionName' => $section->getName() . ($setting->getName() !== null ? ' - ' . $setting->getName() : ''), + 'sectionName' => $sectionName, + 'id' => mb_strtolower(str_replace(' ', '-', $sectionName)), 'priority' => $section->getPriority(), ]; }, $sectionSettings) @@ -128,6 +99,7 @@ class Delegation implements ISettings { $this->initSettingState(); $this->initAvailableGroupState(); $this->initAuthorizedGroupState(); + $this->initialStateService->provideInitialState('authorized-settings-doc-link', $this->urlGenerator->linkToDocs('admin-delegation')); return new TemplateResponse(Application::APP_ID, 'settings/admin/delegation', [], ''); } diff --git a/apps/settings/lib/Settings/Admin/Mail.php b/apps/settings/lib/Settings/Admin/Mail.php index f4c546b27a4..8bf2342a59c 100644 --- a/apps/settings/lib/Settings/Admin/Mail.php +++ b/apps/settings/lib/Settings/Admin/Mail.php @@ -1,67 +1,44 @@ <?php + /** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Admin; use OCP\AppFramework\Http\TemplateResponse; +use OCP\IBinaryFinder; use OCP\IConfig; use OCP\IL10N; +use OCP\Server; use OCP\Settings\IDelegatedSettings; class Mail implements IDelegatedSettings { - /** @var IConfig */ - private $config; - - /** @var IL10N $l */ - private $l; - /** * @param IConfig $config * @param IL10N $l */ - public function __construct(IConfig $config, IL10N $l) { - $this->config = $config; - $this->l = $l; + public function __construct( + private IConfig $config, + private IL10N $l, + ) { } /** * @return TemplateResponse */ public function getForm() { + $finder = Server::get(IBinaryFinder::class); + $parameters = [ // Mail - 'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'), + 'sendmail_is_available' => $finder->findBinaryPath('sendmail') !== false, 'mail_domain' => $this->config->getSystemValue('mail_domain', ''), 'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''), 'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''), 'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''), 'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''), 'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''), - 'mail_smtpauthtype' => $this->config->getSystemValue('mail_smtpauthtype', ''), 'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false), 'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''), 'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''), @@ -88,8 +65,8 @@ class Mail implements IDelegatedSettings { /** * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. * * E.g.: 70 */ diff --git a/apps/settings/lib/Settings/Admin/MailProvider.php b/apps/settings/lib/Settings/Admin/MailProvider.php new file mode 100644 index 00000000000..c1e72378d20 --- /dev/null +++ b/apps/settings/lib/Settings/Admin/MailProvider.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Settings\Settings\Admin; + +use OCP\IL10N; +use OCP\Settings\DeclarativeSettingsTypes; +use OCP\Settings\IDeclarativeSettingsForm; + +class MailProvider implements IDeclarativeSettingsForm { + + public function __construct( + private IL10N $l, + ) { + } + + public function getSchema(): array { + return [ + 'id' => 'mail-provider-support', + 'priority' => 10, + 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, + 'section_id' => 'server', + 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL, + 'title' => $this->l->t('Mail Providers'), + 'description' => $this->l->t('Mail provider enables sending emails directly through the user\'s personal email account. At present, this functionality is limited to calendar invitations. It requires Nextcloud Mail 4.1 and an email account in Nextcloud Mail that matches the user\'s email address in Nextcloud.'), + + 'fields' => [ + [ + 'id' => 'mail_providers_enabled', + 'title' => $this->l->t('Send emails using'), + 'type' => DeclarativeSettingsTypes::RADIO, + 'default' => 1, + 'options' => [ + [ + 'name' => $this->l->t('User\'s email account'), + 'value' => 1 + ], + [ + 'name' => $this->l->t('System email account'), + 'value' => 0 + ], + ], + ], + ], + ]; + } + +} diff --git a/apps/settings/lib/Settings/Admin/Overview.php b/apps/settings/lib/Settings/Admin/Overview.php index 1519ca923c2..355200372f1 100644 --- a/apps/settings/lib/Settings/Admin/Overview.php +++ b/apps/settings/lib/Settings/Admin/Overview.php @@ -1,45 +1,23 @@ <?php + /** - * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Julius Härtl <jus@bitgrid.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Admin; use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; use OCP\IL10N; +use OCP\ServerVersion; use OCP\Settings\IDelegatedSettings; class Overview implements IDelegatedSettings { - /** @var IConfig */ - private $config; - - /** @var IL10N $l*/ - private $l; - - public function __construct(IConfig $config, IL10N $l) { - $this->config = $config; - $this->l = $l; + public function __construct( + private ServerVersion $serverVersion, + private IConfig $config, + private IL10N $l, + ) { } /** @@ -48,6 +26,7 @@ class Overview implements IDelegatedSettings { public function getForm() { $parameters = [ 'checkForWorkingWellKnownSetup' => $this->config->getSystemValue('check_for_working_wellknown_setup', true), + 'version' => $this->serverVersion->getHumanVersion(), ]; return new TemplateResponse('settings', 'settings/admin/overview', $parameters, ''); @@ -62,8 +41,8 @@ class Overview implements IDelegatedSettings { /** * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. * * E.g.: 70 */ @@ -72,7 +51,7 @@ class Overview implements IDelegatedSettings { } public function getName(): ?string { - return $this->l->t('Security & setup warnings'); + return $this->l->t('Security & setup checks'); } public function getAuthorizedAppConfig(): array { diff --git a/apps/settings/lib/Settings/Admin/Security.php b/apps/settings/lib/Settings/Admin/Security.php index 2580c0a3d00..c4efdb478c7 100644 --- a/apps/settings/lib/Settings/Admin/Security.php +++ b/apps/settings/lib/Settings/Admin/Security.php @@ -1,28 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Julius Härtl <jus@bitgrid.net> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Admin; @@ -30,31 +10,21 @@ use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\Encryption\IManager; +use OCP\IURLGenerator; use OCP\IUserManager; use OCP\Settings\ISettings; class Security implements ISettings { + private MandatoryTwoFactor $mandatoryTwoFactor; - /** @var IManager */ - private $manager; - - /** @var IUserManager */ - private $userManager; - - /** @var MandatoryTwoFactor */ - private $mandatoryTwoFactor; - - /** @var IInitialState */ - private $initialState; - - public function __construct(IManager $manager, - IUserManager $userManager, - MandatoryTwoFactor $mandatoryTwoFactor, - IInitialState $initialState) { - $this->manager = $manager; - $this->userManager = $userManager; + public function __construct( + private IManager $manager, + private IUserManager $userManager, + MandatoryTwoFactor $mandatoryTwoFactor, + private IInitialState $initialState, + private IURLGenerator $urlGenerator, + ) { $this->mandatoryTwoFactor = $mandatoryTwoFactor; - $this->initialState = $initialState; } /** @@ -72,21 +42,15 @@ class Security implements ISettings { } } - $this->initialState->provideInitialState( - 'mandatory2FAState', - $this->mandatoryTwoFactor->getState() - ); - - $parameters = [ - // Encryption API - 'encryptionEnabled' => $this->manager->isEnabled(), - 'encryptionReady' => $this->manager->isReady(), - 'externalBackendsEnabled' => count($this->userManager->getBackends()) > 1, - // Modules - 'encryptionModules' => $encryptionModuleList, - ]; + $this->initialState->provideInitialState('mandatory2FAState', $this->mandatoryTwoFactor->getState()); + $this->initialState->provideInitialState('two-factor-admin-doc', $this->urlGenerator->linkToDocs('admin-2fa')); + $this->initialState->provideInitialState('encryption-enabled', $this->manager->isEnabled()); + $this->initialState->provideInitialState('encryption-ready', $this->manager->isReady()); + $this->initialState->provideInitialState('external-backends-enabled', count($this->userManager->getBackends()) > 1); + $this->initialState->provideInitialState('encryption-modules', $encryptionModuleList); + $this->initialState->provideInitialState('encryption-admin-doc', $this->urlGenerator->linkToDocs('admin-encryption')); - return new TemplateResponse('settings', 'settings/admin/security', $parameters, ''); + return new TemplateResponse('settings', 'settings/admin/security', [], ''); } /** @@ -98,8 +62,8 @@ class Security implements ISettings { /** * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. * * E.g.: 70 */ diff --git a/apps/settings/lib/Settings/Admin/Server.php b/apps/settings/lib/Settings/Admin/Server.php index 0fe98f21c8f..c0f29ce8f34 100644 --- a/apps/settings/lib/Settings/Admin/Server.php +++ b/apps/settings/lib/Settings/Admin/Server.php @@ -1,27 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Admin; @@ -30,60 +11,55 @@ use OC\Profile\TProfileHelper; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IDBConnection; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\Settings\IDelegatedSettings; class Server implements IDelegatedSettings { use TProfileHelper; - /** @var IDBConnection */ - private $connection; - /** @var IInitialState */ - private $initialStateService; - /** @var ProfileManager */ - private $profileManager; - /** @var ITimeFactory */ - private $timeFactory; - /** @var IConfig */ - private $config; - /** @var IL10N $l */ - private $l; - - public function __construct(IDBConnection $connection, - IInitialState $initialStateService, - ProfileManager $profileManager, - ITimeFactory $timeFactory, - IConfig $config, - IL10N $l) { - $this->connection = $connection; - $this->initialStateService = $initialStateService; - $this->profileManager = $profileManager; - $this->timeFactory = $timeFactory; - $this->config = $config; - $this->l = $l; + public function __construct( + private IDBConnection $connection, + private IInitialState $initialStateService, + private ProfileManager $profileManager, + private ITimeFactory $timeFactory, + private IURLGenerator $urlGenerator, + private IConfig $config, + private IAppConfig $appConfig, + private IL10N $l, + ) { } /** * @return TemplateResponse */ public function getForm() { - $parameters = [ - // Background jobs - 'backgroundjobs_mode' => $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax'), - 'lastcron' => $this->config->getAppValue('core', 'lastcron', false), - 'cronMaxAge' => $this->cronMaxAge(), - 'cronErrors' => $this->config->getAppValue('core', 'cronErrors'), - 'cli_based_cron_possible' => function_exists('posix_getpwuid'), - 'cli_based_cron_user' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : '', - 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), - ]; + $ownerConfigFile = fileowner(\OC::$configDir . 'config.php'); + $cliBasedCronPossible = function_exists('posix_getpwuid') && $ownerConfigFile !== false; + $cliBasedCronUser = $cliBasedCronPossible ? (posix_getpwuid($ownerConfigFile)['name'] ?? '') : ''; + // Background jobs + $this->initialStateService->provideInitialState('backgroundJobsMode', $this->appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax')); + $this->initialStateService->provideInitialState('lastCron', $this->appConfig->getValueInt('core', 'lastcron', 0)); + $this->initialStateService->provideInitialState('cronMaxAge', $this->cronMaxAge()); + $this->initialStateService->provideInitialState('cronErrors', $this->config->getAppValue('core', 'cronErrors')); + $this->initialStateService->provideInitialState('cliBasedCronPossible', $cliBasedCronPossible); + $this->initialStateService->provideInitialState('cliBasedCronUser', $cliBasedCronUser); + $this->initialStateService->provideInitialState('backgroundJobsDocUrl', $this->urlGenerator->linkToDocs('admin-background-jobs')); + + // Profile page $this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled()); $this->initialStateService->provideInitialState('profileEnabledByDefault', $this->isProfileEnabledByDefault($this->config)); - return new TemplateResponse('settings', 'settings/admin/server', $parameters, ''); + // Basic settings + $this->initialStateService->provideInitialState('restrictSystemTagsCreationToAdmin', $this->appConfig->getValueBool('systemtags', 'restrict_creation_to_admin', false)); + + return new TemplateResponse('settings', 'settings/admin/server', [ + 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), + ], ''); } protected function cronMaxAge(): int { @@ -95,7 +71,7 @@ class Server implements IDelegatedSettings { $result = $query->execute(); if ($row = $result->fetch()) { - $maxAge = (int) $row['last_checked']; + $maxAge = (int)$row['last_checked']; } else { $maxAge = $this->timeFactory->getTime(); } @@ -113,8 +89,8 @@ class Server implements IDelegatedSettings { /** * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. * * E.g.: 70 */ diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php index 56c89c515a8..ec5dcdf624d 100644 --- a/apps/settings/lib/Settings/Admin/Sharing.php +++ b/apps/settings/lib/Settings/Admin/Sharing.php @@ -1,64 +1,35 @@ <?php + /** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sascha Wiswedel <sascha.wiswedel@nextcloud.com> - * @author Vincent Petry <vincent@nextcloud.com> - * @author Thomas Citharel <nextcloud@tcit.fr> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Admin; +use OC\Core\AppInfo\ConfigLexicon; use OCP\App\IAppManager; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Constants; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\Settings\IDelegatedSettings; use OCP\Share\IManager; use OCP\Util; class Sharing implements IDelegatedSettings { - /** @var IConfig */ - private $config; - - /** @var IL10N */ - private $l; - - /** @var IManager */ - private $shareManager; - - /** @var IAppManager */ - private $appManager; - - public function __construct(IConfig $config, IL10N $l, IManager $shareManager, IAppManager $appManager) { - $this->config = $config; - $this->l = $l; - $this->shareManager = $shareManager; - $this->appManager = $appManager; + public function __construct( + private IConfig $config, + private IAppConfig $appConfig, + private IL10N $l, + private IManager $shareManager, + private IAppManager $appManager, + private IURLGenerator $urlGenerator, + private IInitialState $initialState, + private string $appName, + ) { } /** @@ -66,84 +37,62 @@ class Sharing implements IDelegatedSettings { */ public function getForm() { $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', ''); - $excludeGroupsList = !is_null(json_decode($excludedGroups)) - ? implode('|', json_decode($excludedGroups, true)) : ''; $linksExcludedGroups = $this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', ''); - $linksExcludeGroupsList = !is_null(json_decode($linksExcludedGroups)) - ? implode('|', json_decode($linksExcludedGroups, true)) : ''; - $excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', ''); - $excludedPasswordGroupsList = !is_null(json_decode($excludedPasswordGroups)) - ? implode('|', json_decode($excludedPasswordGroups, true)) : ''; - + $onlyShareWithGroupMembersExcludeGroupList = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''); $parameters = [ // Built-In Sharing - 'sharingAppEnabled' => $this->appManager->isEnabledForUser('files_sharing'), - 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'), - 'allowLinks' => $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'), - 'allowLinksExcludeGroups' => $linksExcludeGroupsList, - 'allowPublicUpload' => $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'), - 'allowResharing' => $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes'), - 'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'), - 'restrictUserEnumerationToGroup' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no'), - 'restrictUserEnumerationToPhone' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no'), - 'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'), - 'restrictUserEnumerationFullMatchUserId' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_userid', 'yes'), - 'restrictUserEnumerationFullMatchIgnoreSecondDisplayName' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_display_name', 'no'), - 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(false), - 'passwordExcludedGroups' => $excludedPasswordGroupsList, - 'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false), + 'enabled' => $this->getHumanBooleanConfig('core', 'shareapi_enabled', true), + 'allowGroupSharing' => $this->getHumanBooleanConfig('core', 'shareapi_allow_group_sharing', true), + 'allowLinks' => $this->getHumanBooleanConfig('core', 'shareapi_allow_links', true), + 'allowLinksExcludeGroups' => json_decode($linksExcludedGroups, true) ?? [], + 'allowPublicUpload' => $this->getHumanBooleanConfig('core', 'shareapi_allow_public_upload', true), + 'allowResharing' => $this->getHumanBooleanConfig('core', 'shareapi_allow_resharing', true), + 'allowShareDialogUserEnumeration' => $this->getHumanBooleanConfig('core', 'shareapi_allow_share_dialog_user_enumeration', true), + 'allowFederationOnPublicShares' => $this->appConfig->getValueBool('core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES), + 'restrictUserEnumerationToGroup' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_to_group'), + 'restrictUserEnumerationToPhone' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_to_phone'), + 'restrictUserEnumerationFullMatch' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_full_match', true), + 'restrictUserEnumerationFullMatchUserId' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_full_match_userid', true), + 'restrictUserEnumerationFullMatchEmail' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_full_match_email', true), + 'restrictUserEnumerationFullMatchIgnoreSecondDN' => $this->getHumanBooleanConfig('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn'), + 'enforceLinksPassword' => Util::isPublicLinkPasswordRequired(false), + 'enforceLinksPasswordExcludedGroups' => json_decode($excludedPasswordGroups) ?? [], + 'enforceLinksPasswordExcludedGroupsEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false), 'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(), - 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'), - 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'), - 'shareExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'), - 'shareEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no'), - 'shareExcludeGroups' => $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes', - 'shareExcludedGroupsList' => $excludeGroupsList, - 'publicShareDisclaimerText' => $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null), - 'enableLinkPasswordByDefault' => $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no'), - 'shareApiDefaultPermissions' => $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL), - 'shareApiDefaultPermissionsCheckboxes' => $this->getSharePermissionList(), - 'shareDefaultInternalExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no'), - 'shareInternalExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7'), - 'shareInternalEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no'), - 'shareDefaultRemoteExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no'), - 'shareRemoteExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7'), - 'shareRemoteEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no'), + 'onlyShareWithGroupMembersExcludeGroupList' => json_decode($onlyShareWithGroupMembersExcludeGroupList) ?? [], + 'defaultExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_default_expire_date'), + 'expireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'), + 'enforceExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_enforce_expire_date'), + 'excludeGroups' => $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no'), + 'excludeGroupsList' => json_decode($excludedGroups, true) ?? [], + 'publicShareDisclaimerText' => $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext'), + 'enableLinkPasswordByDefault' => $this->appConfig->getValueBool('core', ConfigLexicon::SHARE_LINK_PASSWORD_DEFAULT), + 'defaultPermissions' => (int)$this->config->getAppValue('core', 'shareapi_default_permissions', (string)Constants::PERMISSION_ALL), + 'defaultInternalExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_default_internal_expire_date'), + 'internalExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7'), + 'enforceInternalExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_enforce_internal_expire_date'), + 'defaultRemoteExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_default_remote_expire_date'), + 'remoteExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7'), + 'enforceRemoteExpireDate' => $this->getHumanBooleanConfig('core', 'shareapi_enforce_remote_expire_date'), + 'allowCustomTokens' => $this->shareManager->allowCustomTokens(), + 'allowViewWithoutDownload' => $this->shareManager->allowViewWithoutDownload(), ]; - return new TemplateResponse('settings', 'settings/admin/sharing', $parameters, ''); + $this->initialState->provideInitialState('sharingAppEnabled', $this->appManager->isEnabledForUser('files_sharing')); + $this->initialState->provideInitialState('sharingDocumentation', $this->urlGenerator->linkToDocs('admin-sharing')); + $this->initialState->provideInitialState('sharingSettings', $parameters); + + Util::addScript($this->appName, 'vue-settings-admin-sharing'); + return new TemplateResponse($this->appName, 'settings/admin/sharing', [], ''); } /** - * get share permission list for template - * - * @return array + * Helper function to retrive boolean values from human readable strings ('yes' / 'no') */ - private function getSharePermissionList() { - return [ - [ - 'id' => 'cancreate', - 'label' => $this->l->t('Create'), - 'value' => Constants::PERMISSION_CREATE - ], - [ - 'id' => 'canupdate', - 'label' => $this->l->t('Change'), - 'value' => Constants::PERMISSION_UPDATE - ], - [ - 'id' => 'candelete', - 'label' => $this->l->t('Delete'), - 'value' => Constants::PERMISSION_DELETE - ], - [ - 'id' => 'canshare', - 'label' => $this->l->t('Reshare'), - 'value' => Constants::PERMISSION_SHARE - ], - ]; + private function getHumanBooleanConfig(string $app, string $key, bool $default = false): bool { + return $this->config->getAppValue($app, $key, $default ? 'yes' : 'no') === 'yes'; } /** @@ -155,8 +104,8 @@ class Sharing implements IDelegatedSettings { /** * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. * * E.g.: 70 */ diff --git a/apps/settings/lib/Settings/Admin/Users.php b/apps/settings/lib/Settings/Admin/Users.php new file mode 100644 index 00000000000..c569890a0dc --- /dev/null +++ b/apps/settings/lib/Settings/Admin/Users.php @@ -0,0 +1,61 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\Settings\Settings\Admin; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IL10N; +use OCP\Settings\IDelegatedSettings; + +/** + * Empty settings class, used only for admin delegation. + */ +class Users implements IDelegatedSettings { + + public function __construct( + protected string $appName, + private IL10N $l10n, + ) { + } + + /** + * Empty template response + */ + public function getForm(): TemplateResponse { + + return new /** @template-extends TemplateResponse<\OCP\AppFramework\Http::STATUS_OK, array{}> */ class($this->appName, '') extends TemplateResponse { + public function render(): string { + return ''; + } + }; + } + + public function getSection(): ?string { + return 'admindelegation'; + } + + /** + * @return int whether the form should be rather on the top or bottom of + * the admin section. The forms are arranged in ascending order of the + * priority values. It is required to return a value between 0 and 100. + * + * E.g.: 70 + */ + public function getPriority(): int { + return 0; + } + + public function getName(): string { + return $this->l10n->t('Users'); + } + + public function getAuthorizedAppConfig(): array { + return []; + } +} |