diff options
Diffstat (limited to 'apps/settings/lib/Settings')
16 files changed, 897 insertions, 657 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 new file mode 100644 index 00000000000..59a26d1ac04 --- /dev/null +++ b/apps/settings/lib/Settings/Admin/Delegation.php @@ -0,0 +1,120 @@ +<?php + +/** + * 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; +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 { + public function __construct( + private IManager $settingManager, + private IInitialState $initialStateService, + private IGroupManager $groupManager, + private AuthorizedGroupService $authorizedGroupService, + private IURLGenerator $urlGenerator, + ) { + } + + /** + * Filter out the ISettings that are not IDelegatedSettings from $innerSection + * and add them to $settings. + * + * @param IDelegatedSettings[] $settings + * @param ISettings[] $innerSection + * @return IDelegatedSettings[] + */ + private function getDelegatedSettings(array $settings, array $innerSection): array { + foreach ($innerSection as $setting) { + if ($setting instanceof IDelegatedSettings) { + $settings[] = $setting; + } + } + return $settings; + } + + private function initSettingState(): void { + // Available settings page initialization + $sections = $this->settingManager->getAdminSections(); + $settings = []; + foreach ($sections as $sectionPriority) { + foreach ($sectionPriority as $section) { + $sectionSettings = $this->settingManager->getAdminSettings($section->getId()); + $sectionSettings = array_reduce($sectionSettings, [$this, 'getDelegatedSettings'], []); + $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' => $sectionName, + 'id' => mb_strtolower(str_replace(' ', '-', $sectionName)), + 'priority' => $section->getPriority(), + ]; + }, $sectionSettings) + ); + } + } + usort($settings, function (array $a, array $b) { + if ($a['priority'] == $b['priority']) { + return 0; + } + return ($a['priority'] < $b['priority']) ? -1 : 1; + }); + $this->initialStateService->provideInitialState('available-settings', $settings); + } + + public function initAvailableGroupState(): void { + // Available groups initialization + $groups = []; + $groupsClass = $this->groupManager->search(''); + foreach ($groupsClass as $group) { + if ($group->getGID() === 'admin') { + continue; // Admin already have access to everything + } + $groups[] = [ + 'displayName' => $group->getDisplayName(), + 'gid' => $group->getGID(), + ]; + } + $this->initialStateService->provideInitialState('available-groups', $groups); + } + + public function initAuthorizedGroupState(): void { + // Already set authorized groups + $this->initialStateService->provideInitialState('authorized-groups', $this->authorizedGroupService->findAll()); + } + + public function getForm(): TemplateResponse { + $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', [], ''); + } + + /** + * @return string the section ID, e.g. 'sharing' + */ + public function getSection() { + return 'admindelegation'; + } + + /* + * @inheritdoc + */ + public function getPriority() { + return 75; + } +} diff --git a/apps/settings/lib/Settings/Admin/Mail.php b/apps/settings/lib/Settings/Admin/Mail.php index 75d3f4505c1..8bf2342a59c 100644 --- a/apps/settings/lib/Settings/Admin/Mail.php +++ b/apps/settings/lib/Settings/Admin/Mail.php @@ -1,62 +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\Settings\ISettings; - -class Mail implements ISettings { - /** @var IConfig */ - private $config; +use OCP\IL10N; +use OCP\Server; +use OCP\Settings\IDelegatedSettings; +class Mail implements IDelegatedSettings { /** * @param IConfig $config + * @param IL10N $l */ - public function __construct(IConfig $config) { - $this->config = $config; + 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', ''), @@ -83,12 +65,20 @@ class Mail 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 */ public function getPriority() { return 10; } + + public function getName(): ?string { + return $this->l->t('Email server'); + } + + public function getAuthorizedAppConfig(): array { + return []; + } } 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 ed6a6551f29..355200372f1 100644 --- a/apps/settings/lib/Settings/Admin/Overview.php +++ b/apps/settings/lib/Settings/Admin/Overview.php @@ -1,41 +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\Settings\ISettings; - -class Overview implements ISettings { - /** @var IConfig */ - private $config; - - public function __construct(IConfig $config) { - $this->config = $config; +use OCP\IL10N; +use OCP\ServerVersion; +use OCP\Settings\IDelegatedSettings; + +class Overview implements IDelegatedSettings { + public function __construct( + private ServerVersion $serverVersion, + private IConfig $config, + private IL10N $l, + ) { } /** @@ -44,6 +26,7 @@ class Overview implements ISettings { 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, ''); @@ -58,12 +41,20 @@ class Overview 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 */ public function getPriority() { return 10; } + + public function getName(): ?string { + return $this->l->t('Security & setup checks'); + } + + public function getAuthorizedAppConfig(): array { + return []; + } } diff --git a/apps/settings/lib/Settings/Admin/Security.php b/apps/settings/lib/Settings/Admin/Security.php index a7ff58be68f..c4efdb478c7 100644 --- a/apps/settings/lib/Settings/Admin/Security.php +++ b/apps/settings/lib/Settings/Admin/Security.php @@ -1,67 +1,36 @@ <?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; use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Encryption\IManager; -use OCP\IInitialStateService; +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 IInitialStateService */ - private $initialState; - - public function __construct(IManager $manager, - IUserManager $userManager, - MandatoryTwoFactor $mandatoryTwoFactor, - IInitialStateService $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; } /** * @return TemplateResponse */ - public function getForm() { + public function getForm(): TemplateResponse { $encryptionModules = $this->manager->getEncryptionModules(); $defaultEncryptionModuleId = $this->manager->getDefaultEncryptionModuleId(); $encryptionModuleList = []; @@ -73,39 +42,32 @@ class Security implements ISettings { } } - $this->initialState->provideInitialState( - 'settings', - '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', [], ''); } /** * @return string the section ID, e.g. 'sharing' */ - public function getSection() { + public function getSection(): string { return 'security'; } /** * @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 */ - public function getPriority() { + public function getPriority(): int { return 10; } } diff --git a/apps/settings/lib/Settings/Admin/Server.php b/apps/settings/lib/Settings/Admin/Server.php index 8fb1961719e..c0f29ce8f34 100644 --- a/apps/settings/lib/Settings/Admin/Server.php +++ b/apps/settings/lib/Settings/Admin/Server.php @@ -1,69 +1,65 @@ <?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; +use OC\Profile\ProfileManager; +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\Settings\ISettings; - -class Server implements ISettings { - - /** @var IDBConnection */ - private $connection; - /** @var ITimeFactory */ - private $timeFactory; - /** @var IConfig */ - private $config; - - public function __construct(IDBConnection $connection, - ITimeFactory $timeFactory, - IConfig $config) { - $this->connection = $connection; - $this->timeFactory = $timeFactory; - $this->config = $config; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\Settings\IDelegatedSettings; + +class Server implements IDelegatedSettings { + use TProfileHelper; + + 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'] : '', - ]; + $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 { @@ -75,7 +71,7 @@ class Server implements ISettings { $result = $query->execute(); if ($row = $result->fetch()) { - $maxAge = (int) $row['last_checked']; + $maxAge = (int)$row['last_checked']; } else { $maxAge = $this->timeFactory->getTime(); } @@ -93,12 +89,24 @@ class Server 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 */ public function getPriority(): int { return 0; } + + public function getName(): ?string { + return $this->l->t('Background jobs'); + } + + public function getAuthorizedAppConfig(): array { + return [ + 'core' => [ + '/mail_general_settings/', + ], + ]; + } } diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php index 313a182501d..ec5dcdf624d 100644 --- a/apps/settings/lib/Settings/Admin/Sharing.php +++ b/apps/settings/lib/Settings/Admin/Sharing.php @@ -1,60 +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 Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sascha Wiswedel <sascha.wiswedel@nextcloud.com> - * - * @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\Share\Share; +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\Settings\ISettings; +use OCP\IURLGenerator; +use OCP\Settings\IDelegatedSettings; use OCP\Share\IManager; use OCP\Util; -class Sharing implements ISettings { - /** @var IConfig */ - private $config; - - /** @var IL10N */ - private $l; - - /** @var IManager */ - private $shareManager; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config, IL10N $l, IManager $shareManager) { - $this->config = $config; - $this->l = $l; - $this->shareManager = $shareManager; +class Sharing implements IDelegatedSettings { + 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, + ) { } /** @@ -62,65 +37,62 @@ class Sharing implements ISettings { */ 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', ''); + $excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', ''); + $onlyShareWithGroupMembersExcludeGroupList = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members_exclude_group_list', ''); $parameters = [ // Built-In Sharing - 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'), - 'allowLinks' => $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'), - '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'), - 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(), + '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'), + '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'; } /** @@ -132,12 +104,22 @@ class Sharing 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 */ public function getPriority() { return 0; } + + public function getAuthorizedAppConfig(): array { + return [ + 'core' => ['/shareapi_.*/'], + ]; + } + + public function getName(): ?string { + return null; + } } 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 []; + } +} diff --git a/apps/settings/lib/Settings/Personal/Additional.php b/apps/settings/lib/Settings/Personal/Additional.php index 5fff714b245..58fe08a63b7 100644 --- a/apps/settings/lib/Settings/Personal/Additional.php +++ b/apps/settings/lib/Settings/Personal/Additional.php @@ -1,27 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.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: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal; use OCP\AppFramework\Http\TemplateResponse; @@ -33,7 +15,7 @@ class Additional implements ISettings { * @return TemplateResponse returns the instance with all parameters set, ready to be rendered * @since 9.1 */ - public function getForm() { + public function getForm(): TemplateResponse { return new TemplateResponse('settings', 'settings/empty'); } @@ -41,19 +23,19 @@ class Additional implements ISettings { * @return string the section ID, e.g. 'sharing' * @since 9.1 */ - public function getSection() { + public function getSection(): string { return 'additional'; } /** * @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 * @since 9.1 */ - public function getPriority() { - return '5'; + public function getPriority(): int { + return 5; } } diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php index a853846fadd..9a12b18bb5e 100644 --- a/apps/settings/lib/Settings/Personal/PersonalInfo.php +++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php @@ -3,43 +3,21 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Citharel <nextcloud@tcit.fr> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Settings\Settings\Personal; -use OC\Accounts\AccountManager; +use OC\Profile\ProfileManager; use OCA\FederatedFileSharing\FederatedShareProvider; +use OCA\Provisioning_API\Controller\AUserDataOCSController; +use OCP\Accounts\IAccount; use OCP\Accounts\IAccountManager; +use OCP\Accounts\IAccountProperty; use OCP\App\IAppManager; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Files\FileInfo; use OCP\IConfig; use OCP\IGroup; @@ -48,55 +26,44 @@ use OCP\IL10N; use OCP\IUser; use OCP\IUserManager; use OCP\L10N\IFactory; +use OCP\Notification\IManager; +use OCP\Server; use OCP\Settings\ISettings; +use OCP\Util; class PersonalInfo implements ISettings { - /** @var IConfig */ - private $config; - /** @var IUserManager */ - private $userManager; - /** @var AccountManager */ - private $accountManager; - /** @var IGroupManager */ - private $groupManager; - /** @var IAppManager */ - private $appManager; - /** @var IFactory */ - private $l10nFactory; - /** @var IL10N */ - private $l; + /** @var ProfileManager */ + private $profileManager; public function __construct( - IConfig $config, - IUserManager $userManager, - IGroupManager $groupManager, - AccountManager $accountManager, - IAppManager $appManager, - IFactory $l10nFactory, - IL10N $l + private IConfig $config, + private IUserManager $userManager, + private IGroupManager $groupManager, + private IAccountManager $accountManager, + ProfileManager $profileManager, + private IAppManager $appManager, + private IFactory $l10nFactory, + private IL10N $l, + private IInitialState $initialStateService, + private IManager $manager, ) { - $this->config = $config; - $this->userManager = $userManager; - $this->accountManager = $accountManager; - $this->groupManager = $groupManager; - $this->appManager = $appManager; - $this->l10nFactory = $l10nFactory; - $this->l = $l; + $this->profileManager = $profileManager; } public function getForm(): TemplateResponse { + $federationEnabled = $this->appManager->isEnabledForUser('federation'); $federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing'); $lookupServerUploadEnabled = false; if ($federatedFileSharingEnabled) { /** @var FederatedShareProvider $shareProvider */ - $shareProvider = \OC::$server->query(FederatedShareProvider::class); + $shareProvider = Server::get(FederatedShareProvider::class); $lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled(); } $uid = \OC_User::getUser(); $user = $this->userManager->get($uid); - $userData = $this->accountManager->getUser($user); + $account = $this->accountManager->getAccount($user); // make sure FS is setup before querying storage related stuff... \OC_Util::setupFS($user->getUID()); @@ -105,46 +72,92 @@ class PersonalInfo implements ISettings { if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) { $totalSpace = $this->l->t('Unlimited'); } else { - $totalSpace = \OC_Helper::humanFileSize($storageInfo['total']); + $totalSpace = Util::humanFileSize($storageInfo['total']); } - $languageParameters = $this->getLanguages($user); - $localeParameters = $this->getLocales($user); - $messageParameters = $this->getMessageParameters($userData); + $messageParameters = $this->getMessageParameters($account); $parameters = [ - 'total_space' => $totalSpace, - 'usage' => \OC_Helper::humanFileSize($storageInfo['used']), - 'usage_relative' => round($storageInfo['relative']), + 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, + 'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(), + 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), + ] + $messageParameters; + + $personalInfoParameters = [ + 'userId' => $uid, + 'avatar' => $this->getProperty($account, IAccountManager::PROPERTY_AVATAR), + 'groups' => $this->getGroups($user), 'quota' => $storageInfo['quota'], + 'totalSpace' => $totalSpace, + 'usage' => Util::humanFileSize($storageInfo['used']), + 'usageRelative' => round($storageInfo['relative']), + 'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME), + 'emailMap' => $this->getEmailMap($account), + 'phone' => $this->getProperty($account, IAccountManager::PROPERTY_PHONE), + 'defaultPhoneRegion' => $this->config->getSystemValueString('default_phone_region'), + 'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS), + 'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE), + 'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER), + 'bluesky' => $this->getProperty($account, IAccountManager::PROPERTY_BLUESKY), + 'fediverse' => $this->getProperty($account, IAccountManager::PROPERTY_FEDIVERSE), + 'languageMap' => $this->getLanguageMap($user), + 'localeMap' => $this->getLocaleMap($user), + 'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), + 'profileEnabled' => $this->profileManager->isProfileEnabled($user), + 'organisation' => $this->getProperty($account, IAccountManager::PROPERTY_ORGANISATION), + 'role' => $this->getProperty($account, IAccountManager::PROPERTY_ROLE), + 'headline' => $this->getProperty($account, IAccountManager::PROPERTY_HEADLINE), + 'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY), + 'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE), + 'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK), + 'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS), + ]; + + $accountParameters = [ 'avatarChangeSupported' => $user->canChangeAvatar(), - 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, - 'avatarScope' => $userData[IAccountManager::PROPERTY_AVATAR]['scope'], 'displayNameChangeSupported' => $user->canChangeDisplayName(), - 'displayName' => $userData[IAccountManager::PROPERTY_DISPLAYNAME]['value'], - 'displayNameScope' => $userData[IAccountManager::PROPERTY_DISPLAYNAME]['scope'], - 'email' => $userData[IAccountManager::PROPERTY_EMAIL]['value'], - 'emailScope' => $userData[IAccountManager::PROPERTY_EMAIL]['scope'], - 'emailVerification' => $userData[IAccountManager::PROPERTY_EMAIL]['verified'], - 'phone' => $userData[IAccountManager::PROPERTY_PHONE]['value'], - 'phoneScope' => $userData[IAccountManager::PROPERTY_PHONE]['scope'], - 'address' => $userData[IAccountManager::PROPERTY_ADDRESS]['value'], - 'addressScope' => $userData[IAccountManager::PROPERTY_ADDRESS]['scope'], - 'website' => $userData[IAccountManager::PROPERTY_WEBSITE]['value'], - 'websiteScope' => $userData[IAccountManager::PROPERTY_WEBSITE]['scope'], - 'websiteVerification' => $userData[IAccountManager::PROPERTY_WEBSITE]['verified'], - 'twitter' => $userData[IAccountManager::PROPERTY_TWITTER]['value'], - 'twitterScope' => $userData[IAccountManager::PROPERTY_TWITTER]['scope'], - 'twitterVerification' => $userData[IAccountManager::PROPERTY_TWITTER]['verified'], - 'groups' => $this->getGroups($user), - ] + $messageParameters + $languageParameters + $localeParameters; + 'emailChangeSupported' => $user->canChangeEmail(), + 'federationEnabled' => $federationEnabled, + 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, + ]; + + $profileParameters = [ + 'profileConfig' => $this->profileManager->getProfileConfigWithMetadata($user, $user), + ]; + $this->initialStateService->provideInitialState('profileEnabledGlobally', $this->profileManager->isProfileEnabled()); + $this->initialStateService->provideInitialState('personalInfoParameters', $personalInfoParameters); + $this->initialStateService->provideInitialState('accountParameters', $accountParameters); + $this->initialStateService->provideInitialState('profileParameters', $profileParameters); return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, ''); } /** - * @return string the section ID, e.g. 'sharing' + * Check if is fair use of free push service + * @return boolean + */ + private function isFairUseOfFreePushService(): bool { + return $this->manager->isFairUseOfFreePushService(); + } + + /** + * returns the property data in an + * associative array + */ + private function getProperty(IAccount $account, string $property): array { + $property = [ + 'name' => $account->getProperty($property)->getName(), + 'value' => $account->getProperty($property)->getValue(), + 'scope' => $account->getProperty($property)->getScope(), + 'verified' => $account->getProperty($property)->getVerified(), + ]; + + return $property; + } + + /** + * returns the section ID string, e.g. 'sharing' * @since 9.1 */ public function getSection(): string { @@ -153,8 +166,8 @@ class PersonalInfo 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 * @since 9.1 @@ -165,9 +178,6 @@ class PersonalInfo implements ISettings { /** * returns a sorted list of the user's group GIDs - * - * @param IUser $user - * @return array */ private function getGroups(IUser $user): array { $groups = array_map( @@ -182,13 +192,44 @@ class PersonalInfo implements ISettings { } /** - * returns the user language, common language and other languages in an + * returns the primary email and additional emails in an + * associative array + */ + private function getEmailMap(IAccount $account): array { + $systemEmail = [ + 'name' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getName(), + 'value' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue(), + 'scope' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(), + 'verified' => $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getVerified(), + ]; + + $additionalEmails = array_map( + function (IAccountProperty $property) { + return [ + 'name' => $property->getName(), + 'value' => $property->getValue(), + 'scope' => $property->getScope(), + 'verified' => $property->getVerified(), + 'locallyVerified' => $property->getLocallyVerified(), + ]; + }, + $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)->getProperties(), + ); + + $emailMap = [ + 'primaryEmail' => $systemEmail, + 'additionalEmails' => $additionalEmails, + 'notificationEmail' => (string)$account->getUser()->getPrimaryEMailAddress(), + ]; + + return $emailMap; + } + + /** + * returns the user's active language, common languages, and other languages in an * associative array - * - * @param IUser $user - * @return array */ - private function getLanguages(IUser $user): array { + private function getLanguageMap(IUser $user): array { $forceLanguage = $this->config->getSystemValue('force_language', false); if ($forceLanguage !== false) { return []; @@ -200,12 +241,12 @@ class PersonalInfo implements ISettings { $languages = $this->l10nFactory->getLanguages(); // associate the user language with the proper array - $userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code')); - $userLang = $languages['commonlanguages'][$userLangIndex]; + $userLangIndex = array_search($userConfLang, array_column($languages['commonLanguages'], 'code')); + $userLang = $languages['commonLanguages'][$userLangIndex]; // search in the other languages if ($userLangIndex === false) { - $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code')); - $userLang = $languages['languages'][$userLangIndex]; + $userLangIndex = array_search($userConfLang, array_column($languages['otherLanguages'], 'code')); + $userLang = $languages['otherLanguages'][$userLangIndex]; } // if user language is not available but set somehow: show the actual code as name if (!is_array($userLang)) { @@ -216,36 +257,29 @@ class PersonalInfo implements ISettings { } return array_merge( - ['activelanguage' => $userLang], + ['activeLanguage' => $userLang], $languages ); } - private function getLocales(IUser $user): array { + private function getLocaleMap(IUser $user): array { $forceLanguage = $this->config->getSystemValue('force_locale', false); if ($forceLanguage !== false) { return []; } $uid = $user->getUID(); - - $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale()); - $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage()); - + $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale($userLang)); $localeCodes = $this->l10nFactory->findAvailableLocales(); - - $userLocale = array_filter($localeCodes, function ($value) use ($userLocaleString) { - return $userLocaleString === $value['code']; - }); + $userLocale = array_filter($localeCodes, fn ($value) => $userLocaleString === $value['code']); if (!empty($userLocale)) { $userLocale = reset($userLocale); } - $localesForLanguage = array_filter($localeCodes, function ($localeCode) use ($userLang) { - return 0 === strpos($localeCode['code'], $userLang); - }); + $localesForLanguage = array_values(array_filter($localeCodes, fn ($localeCode) => str_starts_with($localeCode['code'], $userLang))); + $otherLocales = array_values(array_filter($localeCodes, fn ($localeCode) => !str_starts_with($localeCode['code'], $userLang))); if (!$userLocale) { $userLocale = [ @@ -255,26 +289,25 @@ class PersonalInfo implements ISettings { } return [ - 'activelocaleLang' => $userLocaleString, - 'activelocale' => $userLocale, - 'locales' => $localeCodes, + 'activeLocaleLang' => $userLocaleString, + 'activeLocale' => $userLocale, 'localesForLanguage' => $localesForLanguage, + 'otherLocales' => $otherLocales, ]; } /** - * @param array $userData - * @return array + * returns the message parameters */ - private function getMessageParameters(array $userData): array { + private function getMessageParameters(IAccount $account): array { $needVerifyMessage = [IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_WEBSITE, IAccountManager::PROPERTY_TWITTER]; $messageParameters = []; foreach ($needVerifyMessage as $property) { - switch ($userData[$property]['verified']) { - case AccountManager::VERIFIED: + switch ($account->getProperty($property)->getVerified()) { + case IAccountManager::VERIFIED: $message = $this->l->t('Verifying'); break; - case AccountManager::VERIFICATION_IN_PROGRESS: + case IAccountManager::VERIFICATION_IN_PROGRESS: $message = $this->l->t('Verifying …'); break; default: diff --git a/apps/settings/lib/Settings/Personal/Security/Authtokens.php b/apps/settings/lib/Settings/Personal/Security/Authtokens.php index a0758933525..e0509b22a9c 100644 --- a/apps/settings/lib/Settings/Personal/Security/Authtokens.php +++ b/apps/settings/lib/Settings/Personal/Security/Authtokens.php @@ -3,68 +3,32 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.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: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal\Security; -use OCP\AppFramework\Services\IInitialState; -use OCP\IUserSession; -use function array_map; -use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Token\INamedToken; use OC\Authentication\Token\IProvider as IAuthTokenProvider; use OC\Authentication\Token\IToken; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; +use OCP\Authentication\Exceptions\InvalidTokenException; use OCP\ISession; +use OCP\IUserSession; use OCP\Session\Exceptions\SessionNotAvailableException; use OCP\Settings\ISettings; +use function array_map; class Authtokens implements ISettings { - /** @var IAuthTokenProvider */ - private $tokenProvider; - - /** @var ISession */ - private $session; - - /** @var IInitialState */ - private $initialState; - - /** @var string|null */ - private $uid; - - /** @var IUserSession */ - private $userSession; - - public function __construct(IAuthTokenProvider $tokenProvider, - ISession $session, - IUserSession $userSession, - IInitialState $initialState, - ?string $UserId) { - $this->tokenProvider = $tokenProvider; - $this->session = $session; - $this->initialState = $initialState; - $this->uid = $UserId; - $this->userSession = $userSession; + public function __construct( + private IAuthTokenProvider $tokenProvider, + private ISession $session, + private IUserSession $userSession, + private IInitialState $initialState, + private ?string $userId, + ) { } public function getForm(): TemplateResponse { @@ -90,7 +54,7 @@ class Authtokens implements ISettings { } private function getAppTokens(): array { - $tokens = $this->tokenProvider->getTokenByUser($this->uid); + $tokens = $this->tokenProvider->getTokenByUser($this->userId); try { $sessionId = $this->session->getId(); @@ -106,7 +70,7 @@ class Authtokens implements ISettings { return array_map(function (IToken $token) use ($sessionToken) { $data = $token->jsonSerialize(); $data['canDelete'] = true; - $data['canRename'] = $token instanceof INamedToken; + $data['canRename'] = $token instanceof INamedToken && $data['type'] !== IToken::WIPE_TOKEN; if ($sessionToken->getId() === $token->getId()) { $data['canDelete'] = false; $data['canRename'] = false; diff --git a/apps/settings/lib/Settings/Personal/Security/Password.php b/apps/settings/lib/Settings/Personal/Security/Password.php index a3a5ae35cea..8184dae9560 100644 --- a/apps/settings/lib/Settings/Personal/Security/Password.php +++ b/apps/settings/lib/Settings/Personal/Security/Password.php @@ -3,30 +3,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2017 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 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: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal\Security; use OCP\AppFramework\Http\TemplateResponse; @@ -35,20 +14,14 @@ use OCP\Settings\ISettings; class Password implements ISettings { - /** @var IUserManager */ - private $userManager; - - /** @var string|null */ - private $uid; - - public function __construct(IUserManager $userManager, - ?string $UserId) { - $this->userManager = $userManager; - $this->uid = $UserId; + public function __construct( + private IUserManager $userManager, + private ?string $userId, + ) { } public function getForm(): TemplateResponse { - $user = $this->userManager->get($this->uid); + $user = $this->userManager->get($this->userId); $passwordChangeSupported = false; if ($user !== null) { $passwordChangeSupported = $user->canChangePassword(); diff --git a/apps/settings/lib/Settings/Personal/Security/TwoFactor.php b/apps/settings/lib/Settings/Personal/Security/TwoFactor.php index 61f249a3181..0c419cb6fa7 100644 --- a/apps/settings/lib/Settings/Personal/Security/TwoFactor.php +++ b/apps/settings/lib/Settings/Personal/Security/TwoFactor.php @@ -3,42 +3,24 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.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: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal\Security; use Exception; use OC\Authentication\TwoFactorAuth\MandatoryTwoFactor; -use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider; -use function array_filter; -use function array_map; -use function is_null; use OC\Authentication\TwoFactorAuth\ProviderLoader; +use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider; use OCP\AppFramework\Http\TemplateResponse; use OCP\Authentication\TwoFactorAuth\IProvider; use OCP\Authentication\TwoFactorAuth\IProvidesPersonalSettings; use OCP\IConfig; use OCP\IUserSession; use OCP\Settings\ISettings; +use function array_filter; +use function array_map; +use function is_null; class TwoFactor implements ISettings { @@ -48,31 +30,20 @@ class TwoFactor implements ISettings { /** @var MandatoryTwoFactor */ private $mandatoryTwoFactor; - /** @var IUserSession */ - private $userSession; - - /** @var string|null */ - private $uid; - - /** @var IConfig */ - private $config; - - public function __construct(ProviderLoader $providerLoader, - MandatoryTwoFactor $mandatoryTwoFactor, - IUserSession $userSession, - IConfig $config, - ?string $UserId) { + public function __construct( + ProviderLoader $providerLoader, + MandatoryTwoFactor $mandatoryTwoFactor, + private IUserSession $userSession, + private IConfig $config, + private ?string $userId, + ) { $this->providerLoader = $providerLoader; $this->mandatoryTwoFactor = $mandatoryTwoFactor; - $this->userSession = $userSession; - $this->uid = $UserId; - $this->config = $config; } public function getForm(): TemplateResponse { return new TemplateResponse('settings', 'settings/personal/security/twofactor', [ 'twoFactorProviderData' => $this->getTwoFactorProviderData(), - 'themedark' => $this->config->getUserValue($this->uid, 'accessibility', 'theme', false) ]); } diff --git a/apps/settings/lib/Settings/Personal/Security/WebAuthn.php b/apps/settings/lib/Settings/Personal/Security/WebAuthn.php index e3d087a4e06..a6ba4e9522a 100644 --- a/apps/settings/lib/Settings/Personal/Security/WebAuthn.php +++ b/apps/settings/lib/Settings/Personal/Security/WebAuthn.php @@ -3,27 +3,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal\Security; use OC\Authentication\WebAuthn\Db\PublicKeyCredentialMapper; @@ -38,22 +20,16 @@ class WebAuthn implements ISettings { /** @var PublicKeyCredentialMapper */ private $mapper; - /** @var string */ - private $uid; - - /** @var IInitialStateService */ - private $initialStateService; - /** @var Manager */ private $manager; - public function __construct(PublicKeyCredentialMapper $mapper, - string $UserId, - IInitialStateService $initialStateService, - Manager $manager) { + public function __construct( + PublicKeyCredentialMapper $mapper, + private string $userId, + private IInitialStateService $initialStateService, + Manager $manager, + ) { $this->mapper = $mapper; - $this->uid = $UserId; - $this->initialStateService = $initialStateService; $this->manager = $manager; } @@ -61,11 +37,10 @@ class WebAuthn implements ISettings { $this->initialStateService->provideInitialState( Application::APP_ID, 'webauthn-devices', - $this->mapper->findAllForUid($this->uid) + $this->mapper->findAllForUid($this->userId) ); - return new TemplateResponse('settings', 'settings/personal/security/webauthn', [ - ]); + return new TemplateResponse('settings', 'settings/personal/security/webauthn'); } public function getSection(): ?string { diff --git a/apps/settings/lib/Settings/Personal/ServerDevNotice.php b/apps/settings/lib/Settings/Personal/ServerDevNotice.php index 1c1c870d8e9..c9993484abd 100644 --- a/apps/settings/lib/Settings/Personal/ServerDevNotice.php +++ b/apps/settings/lib/Settings/Personal/ServerDevNotice.php @@ -1,29 +1,9 @@ <?php + /** - * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Jan C. Borchardt <hey@jancborchardt.net> - * @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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Settings\Settings\Personal; use OCA\Viewer\Event\LoadViewer; @@ -39,51 +19,29 @@ use OCP\Util; class ServerDevNotice implements ISettings { - /** @var IRegistry */ - private $registry; - - /** @var IEventDispatcher */ - private $eventDispatcher; - - /** @var IRootFolder */ - private $rootFolder; - - /** @var IUserSession */ - private $userSession; - - /** @var IInitialState */ - private $initialState; - - /** @var IURLGenerator */ - private $urlGenerator; - - public function __construct(IRegistry $registry, - IEventDispatcher $eventDispatcher, - IRootFolder $rootFolder, - IUserSession $userSession, - IInitialState $initialState, - IURLGenerator $urlGenerator) { - $this->registry = $registry; - $this->eventDispatcher = $eventDispatcher; - $this->rootFolder = $rootFolder; - $this->userSession = $userSession; - $this->initialState = $initialState; - $this->urlGenerator = $urlGenerator; + public function __construct( + private IRegistry $registry, + private IEventDispatcher $eventDispatcher, + private IRootFolder $rootFolder, + private IUserSession $userSession, + private IInitialState $initialState, + private IURLGenerator $urlGenerator, + ) { } /** * @return TemplateResponse */ - public function getForm() { + public function getForm(): TemplateResponse { $userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID()); $hasInitialState = false; - // viewer is default enabled and this makes a zero-cost assertion for Psalm - assert(class_exists(LoadViewer::class)); - - // If the Reasons to use Nextcloud.pdf file is here, let's init Viewer - if ($userFolder->nodeExists('Reasons to use Nextcloud.pdf')) { + // If the Reasons to use Nextcloud.pdf file is here, let's init Viewer, also check that Viewer is there + if (class_exists(LoadViewer::class) && $userFolder->nodeExists('Reasons to use Nextcloud.pdf')) { + /** + * @psalm-suppress UndefinedClass, InvalidArgument + */ $this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer()); $hasInitialState = true; } @@ -98,9 +56,9 @@ class ServerDevNotice implements ISettings { } /** - * @return string the section ID, e.g. 'sharing' + * @return string|null the section ID, e.g. 'sharing' */ - public function getSection() { + public function getSection(): ?string { if ($this->registry->delegateHasValidSubscription()) { return null; } @@ -110,12 +68,12 @@ class ServerDevNotice 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 */ - public function getPriority() { + public function getPriority(): int { return 1000; } } |