diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-09-28 19:45:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-28 19:45:36 +0200 |
commit | a0b2297c536923867ed3f8e489dabe8a278ac0be (patch) | |
tree | c8d14a6dc5db9c892d6a3bec0a012c99babcaf2a /apps | |
parent | 31ad1c5f552265d3e58496cde85914e58f0e3e2d (diff) | |
parent | b5256181a49813063a8e6490316f7eed3a4341d5 (diff) | |
download | nextcloud-server-a0b2297c536923867ed3f8e489dabe8a278ac0be.tar.gz nextcloud-server-a0b2297c536923867ed3f8e489dabe8a278ac0be.zip |
Merge pull request #48424 from nextcloud/fix/declarative-settings-priority
fix(settings): Sort all settings - incl declarative settings - by priority
Diffstat (limited to 'apps')
4 files changed, 72 insertions, 79 deletions
diff --git a/apps/settings/lib/Controller/AdminSettingsController.php b/apps/settings/lib/Controller/AdminSettingsController.php index 25338f64326..2b731c5cdde 100644 --- a/apps/settings/lib/Controller/AdminSettingsController.php +++ b/apps/settings/lib/Controller/AdminSettingsController.php @@ -5,7 +5,6 @@ */ namespace OCA\Settings\Controller; -use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; @@ -16,7 +15,6 @@ use OCP\Group\ISubAdmin; use OCP\IGroupManager; use OCP\INavigationManager; use OCP\IRequest; -use OCP\IUser; use OCP\IUserSession; use OCP\Settings\IDeclarativeManager; use OCP\Settings\IManager as ISettingsManager; @@ -49,27 +47,14 @@ class AdminSettingsController extends Controller { /** * @NoSubAdminRequired * We are checking the permissions in the getSettings method. If there is no allowed - * settings for the given section. The user will be gretted by an error message. + * settings for the given section. The user will be greeted by an error message. */ #[NoAdminRequired] #[NoCSRFRequired] public function index(string $section): TemplateResponse { - return $this->getIndexResponse('admin', $section); - } - - /** - * @param string $section - * @return array - */ - protected function getSettings($section) { - /** @var IUser $user */ - $user = $this->userSession->getUser(); - $settings = $this->settingsManager->getAllowedAdminSettings($section, $user); - $declarativeFormIDs = $this->declarativeSettingsManager->getFormIDs($user, 'admin', $section); - if (empty($settings) && empty($declarativeFormIDs)) { - throw new NotAdminException("Logged in user doesn't have permission to access these settings."); - } - $formatted = $this->formatSettings($settings); - return $formatted; + return $this->getIndexResponse( + 'admin', + $section, + ); } } diff --git a/apps/settings/lib/Controller/CommonSettingsTrait.php b/apps/settings/lib/Controller/CommonSettingsTrait.php index dd307b67fab..26cbadd76a1 100644 --- a/apps/settings/lib/Controller/CommonSettingsTrait.php +++ b/apps/settings/lib/Controller/CommonSettingsTrait.php @@ -6,6 +6,8 @@ namespace OCA\Settings\Controller; +use InvalidArgumentException; +use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException; use OCA\Settings\AppInfo\Application; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; @@ -21,7 +23,8 @@ use OCP\Settings\ISettings; use OCP\Util; /** - * @psalm-import-type DeclarativeSettingsFormField from IDeclarativeSettingsForm + * @psalm-import-type DeclarativeSettingsFormSchemaWithValues from IDeclarativeSettingsForm + * @psalm-import-type DeclarativeSettingsFormSchemaWithoutValues from IDeclarativeSettingsForm */ trait CommonSettingsTrait { @@ -106,16 +109,26 @@ trait CommonSettingsTrait { } /** - * @param array<int, list<\OCP\Settings\ISettings>> $settings + * @param list<\OCP\Settings\ISettings> $settings + * @param list<DeclarativeSettingsFormSchemaWithValues> $declarativeSettings * @return array{content: string} */ - private function formatSettings(array $settings): array { + private function formatSettings(array $settings, array $declarativeSettings): array { + $settings = array_merge($settings, $declarativeSettings); + + usort($settings, function ($first, $second) { + $priorityOne = $first instanceof ISettings ? $first->getPriority() : $first['priority']; + $priorityTwo = $second instanceof ISettings ? $second->getPriority() : $second['priority']; + return $priorityOne - $priorityTwo; + }); + $html = ''; - foreach ($settings as $prioritizedSettings) { - foreach ($prioritizedSettings as $setting) { - /** @var ISettings $setting */ + foreach ($settings as $setting) { + if ($setting instanceof ISettings) { $form = $setting->getForm(); $html .= $form->renderAs('')->render(); + } else { + $html .= '<div id="' . $setting['app'] . '_' . $setting['id'] . '"></div>'; } } return ['content' => $html]; @@ -125,34 +138,38 @@ trait CommonSettingsTrait { * @psalm-param 'admin'|'personal' $type */ private function getIndexResponse(string $type, string $section): TemplateResponse { + $user = $this->userSession->getUser(); + assert($user !== null, 'No user logged in for settings'); + + $this->declarativeSettingsManager->loadSchemas(); + $declarativeSettings = $this->declarativeSettingsManager->getFormsWithValues($user, $type, $section); + if ($type === 'personal') { + $settings = array_values($this->settingsManager->getPersonalSettings($section)); if ($section === 'theming') { $this->navigationManager->setActiveEntry('accessibility_settings'); } else { $this->navigationManager->setActiveEntry('settings'); } } elseif ($type === 'admin') { + $settings = array_values($this->settingsManager->getAllowedAdminSettings($section, $user)); + if (empty($settings) && empty($declarativeSettings)) { + throw new NotAdminException('Logged in user does not have permission to access these settings.'); + } $this->navigationManager->setActiveEntry('admin_settings'); + } else { + throw new InvalidArgumentException('$type must be either "admin" or "personal"'); } - $this->declarativeSettingsManager->loadSchemas(); - - $templateParams = []; - $templateParams = array_merge($templateParams, $this->getNavigationParameters($type, $section)); - $templateParams = array_merge($templateParams, $this->getSettings($section)); - - /** @psalm-suppress PossiblyNullArgument */ - $declarativeFormIDs = $this->declarativeSettingsManager->getFormIDs($this->userSession->getUser(), $type, $section); - if (!empty($declarativeFormIDs)) { - foreach ($declarativeFormIDs as $app => $ids) { - /** @psalm-suppress PossiblyUndefinedArrayOffset */ - $templateParams['content'] .= join(array_map(fn (string $id) => '<div id="' . $app . '_' . $id . '"></div>', $ids)); - } + if (!empty($declarativeSettings)) { Util::addScript(Application::APP_ID, 'declarative-settings-forms'); - /** @psalm-suppress PossiblyNullArgument */ - $this->initialState->provideInitialState('declarative-settings-forms', $this->declarativeSettingsManager->getFormsWithValues($this->userSession->getUser(), $type, $section)); + $this->initialState->provideInitialState('declarative-settings-forms', $declarativeSettings); } + $settings = array_merge(...$settings); + $templateParams = $this->formatSettings($settings, $declarativeSettings); + $templateParams = array_merge($templateParams, $this->getNavigationParameters($type, $section)); + $activeSection = $this->settingsManager->getSection($type, $section); if ($activeSection) { $templateParams['pageTitle'] = $activeSection->getName(); @@ -162,6 +179,4 @@ trait CommonSettingsTrait { return new TemplateResponse('settings', 'settings/frame', $templateParams); } - - abstract protected function getSettings($section); } diff --git a/apps/settings/lib/Controller/PersonalSettingsController.php b/apps/settings/lib/Controller/PersonalSettingsController.php index 1a31a20eb04..0a87181c7d7 100644 --- a/apps/settings/lib/Controller/PersonalSettingsController.php +++ b/apps/settings/lib/Controller/PersonalSettingsController.php @@ -50,16 +50,9 @@ class PersonalSettingsController extends Controller { #[NoAdminRequired] #[NoCSRFRequired] public function index(string $section): TemplateResponse { - return $this->getIndexResponse('personal', $section); - } - - /** - * @param string $section - * @return array - */ - protected function getSettings($section) { - $settings = $this->settingsManager->getPersonalSettings($section); - $formatted = $this->formatSettings($settings); - return $formatted; + return $this->getIndexResponse( + 'personal', + $section, + ); } } diff --git a/apps/settings/tests/Controller/AdminSettingsControllerTest.php b/apps/settings/tests/Controller/AdminSettingsControllerTest.php index 60ba5e0750e..c8ba8edb968 100644 --- a/apps/settings/tests/Controller/AdminSettingsControllerTest.php +++ b/apps/settings/tests/Controller/AdminSettingsControllerTest.php @@ -14,6 +14,7 @@ use OCP\IGroupManager; use OCP\INavigationManager; use OCP\IRequest; use OCP\IUser; +use OCP\IUserManager; use OCP\IUserSession; use OCP\Settings\IDeclarativeManager; use OCP\Settings\IManager; @@ -29,26 +30,17 @@ use Test\TestCase; */ class AdminSettingsControllerTest extends TestCase { - /** @var AdminSettingsController */ - private $adminSettingsController; - /** @var IRequest|MockObject */ - private $request; - /** @var INavigationManager|MockObject */ - private $navigationManager; - /** @var IManager|MockObject */ - private $settingsManager; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IGroupManager|MockObject */ - private $groupManager; - /** @var ISubAdmin|MockObject */ - private $subAdmin; - /** @var IDeclarativeManager|MockObject */ - private $declarativeSettingsManager; - /** @var IInitialState|MockObject */ - private $initialState; - /** @var string */ - private $adminUid = 'lololo'; + private IRequest&MockObject $request; + private INavigationManager&MockObject $navigationManager; + private IManager&MockObject $settingsManager; + private IUserSession&MockObject $userSession; + private IGroupManager&MockObject $groupManager; + private ISubAdmin&MockObject $subAdmin; + private IDeclarativeManager&MockObject $declarativeSettingsManager; + private IInitialState&MockObject $initialState; + + private string $adminUid = 'lololo'; + private AdminSettingsController $adminSettingsController; protected function setUp(): void { parent::setUp(); @@ -74,15 +66,17 @@ class AdminSettingsControllerTest extends TestCase { $this->initialState, ); - $user = \OC::$server->getUserManager()->createUser($this->adminUid, 'mylongrandompassword'); + $user = \OCP\Server::get(IUserManager::class)->createUser($this->adminUid, 'mylongrandompassword'); \OC_User::setUserId($user->getUID()); - \OC::$server->getGroupManager()->createGroup('admin')->addUser($user); + \OCP\Server::get(IGroupManager::class)->createGroup('admin')->addUser($user); } protected function tearDown(): void { - \OC::$server->getUserManager()->get($this->adminUid)->delete(); + \OCP\Server::get(IUserManager::class) + ->get($this->adminUid) + ->delete(); \OC_User::setUserId(null); - \OC::$server->getUserSession()->setUser(null); + \OCP\Server::get(IUserSession::class)->setUser(null); parent::tearDown(); } @@ -101,6 +95,12 @@ class AdminSettingsControllerTest extends TestCase { ->method('isSubAdmin') ->with($user) ->willReturn(false); + + $form = new TemplateResponse('settings', 'settings/empty'); + $setting = $this->createMock(ServerDevNotice::class); + $setting->expects(self::any()) + ->method('getForm') + ->willReturn($form); $this->settingsManager ->expects($this->once()) ->method('getAdminSections') @@ -113,7 +113,7 @@ class AdminSettingsControllerTest extends TestCase { ->expects($this->once()) ->method('getAllowedAdminSettings') ->with('test') - ->willReturn([5 => $this->createMock(ServerDevNotice::class)]); + ->willReturn([5 => [$setting]]); $this->declarativeSettingsManager ->expects($this->any()) ->method('getFormIDs') |