From 952db800a7657f049ffe62c6e5fff2daa067cf26 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Fri, 27 Mar 2026 13:35:10 +0100 Subject: [PATCH 1/2] feat(settings): implement IDelegatedSettings Signed-off-by: Misha M.-Kupriyanov --- lib/Settings/Admin.php | 14 +++++++++++-- tests/unit/Settings/AdminTest.php | 35 ++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 902a4a1be..eb38a0c2a 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -12,10 +12,10 @@ use OCP\Defaults; use OCP\IConfig; use OCP\IL10N; -use OCP\Settings\ISettings; +use OCP\Settings\IDelegatedSettings; use OneLogin\Saml2\Constants; -class Admin implements ISettings { +class Admin implements IDelegatedSettings { public function __construct( private readonly IL10N $l10n, @@ -254,4 +254,14 @@ public function getSection() { public function getPriority() { return 0; } + + #[\Override] + public function getName(): ?string { + return $this->l10n->t('SSO & SAML authentication'); + } + + #[\Override] + public function getAuthorizedAppConfig(): array { + return []; + } } diff --git a/tests/unit/Settings/AdminTest.php b/tests/unit/Settings/AdminTest.php index 87e6a543e..c5296a556 100644 --- a/tests/unit/Settings/AdminTest.php +++ b/tests/unit/Settings/AdminTest.php @@ -1,5 +1,7 @@ l10n = $this->createMock(IL10N::class); @@ -289,4 +286,22 @@ public function testGetSection() { public function testGetPriority() { $this->assertSame(0, $this->admin->getPriority()); } + + public function testGetName(): void { + $this->l10n->expects($this->once()) + ->method('t') + ->with('SSO & SAML authentication') + ->willReturn('SSO & SAML authentication'); + + $this->assertSame('SSO & SAML authentication', $this->admin->getName()); + } + + public function testGetAuthorizedAppConfig(): void { + $this->assertSame([], $this->admin->getAuthorizedAppConfig()); + } + + public function testImplementsIDelegatedSettings(): void { + $this->assertInstanceOf(\OCP\Settings\IDelegatedSettings::class, $this->admin); + $this->assertInstanceOf(\OCP\Settings\ISettings::class, $this->admin); + } } From 58e2510929778051c5ae7b64d293fa9c39b8a6e1 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Fri, 27 Mar 2026 13:35:28 +0100 Subject: [PATCH 2/2] feat(settings): add AuthorizedAdminSetting to SettingsController - populate getAuthorizedAppConfig() with global oc_appconfig keys: type, general-require_provisioned_account, general-allow_multiple_user_back_ends, directLoginName - add #[AuthorizedAdminSetting(Admin::class)] to all SettingsController methods (reads + writes) so delegated admins can load and save settings Signed-off-by: Misha M.-Kupriyanov --- lib/Controller/SettingsController.php | 6 ++++++ lib/Settings/Admin.php | 9 ++++++++- tests/unit/Settings/AdminTest.php | 10 +++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index ba777fa0c..518bcc687 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -10,6 +10,7 @@ use OCA\User_SAML\SAMLSettings; use OCA\User_SAML\Settings\Admin; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\Response; use OCP\IConfig; @@ -28,6 +29,7 @@ public function __construct( parent::__construct($appName, $request); } + #[AuthorizedAdminSetting(Admin::class)] public function getSamlProviderIds(): DataResponse { $keys = array_keys($this->samlSettings->getListOfIdps()); return new DataResponse([ 'providerIds' => implode(',', $keys)]); @@ -36,6 +38,7 @@ public function getSamlProviderIds(): DataResponse { /** * @return array of categories containing entries for each config parameter with their value */ + #[AuthorizedAdminSetting(Admin::class)] public function getSamlProviderSettings(int $providerId): array { /** * This uses the list of available config parameters from the admin section @@ -90,11 +93,13 @@ public function getSamlProviderSettings(int $providerId): array { return $settings; } + #[AuthorizedAdminSetting(Admin::class)] public function deleteSamlProviderSettings($providerId): Response { $this->samlSettings->delete($providerId); return new Response(); } + #[AuthorizedAdminSetting(Admin::class)] public function setProviderSetting(int $providerId, string $configKey, string $configValue): Response { $configuration = $this->samlSettings->get($providerId); $configuration[$configKey] = $configValue; @@ -102,6 +107,7 @@ public function setProviderSetting(int $providerId, string $configKey, string $c return new Response(); } + #[AuthorizedAdminSetting(Admin::class)] public function newSamlProviderSettingsId(): DataResponse { return new DataResponse(['id' => $this->samlSettings->getNewProviderId()]); } diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index eb38a0c2a..f1baf7c9f 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -262,6 +262,13 @@ public function getName(): ?string { #[\Override] public function getAuthorizedAppConfig(): array { - return []; + return [ + 'user_saml' => [ + 'type', + 'general-require_provisioned_account', + 'general-allow_multiple_user_back_ends', + 'directLoginName', + ], + ]; } } diff --git a/tests/unit/Settings/AdminTest.php b/tests/unit/Settings/AdminTest.php index c5296a556..ecb230969 100644 --- a/tests/unit/Settings/AdminTest.php +++ b/tests/unit/Settings/AdminTest.php @@ -297,7 +297,15 @@ public function testGetName(): void { } public function testGetAuthorizedAppConfig(): void { - $this->assertSame([], $this->admin->getAuthorizedAppConfig()); + $config = $this->admin->getAuthorizedAppConfig(); + + $this->assertArrayHasKey('user_saml', $config); + + $keys = $config['user_saml']; + $this->assertContains('type', $keys); + $this->assertContains('general-require_provisioned_account', $keys); + $this->assertContains('general-allow_multiple_user_back_ends', $keys); + $this->assertContains('directLoginName', $keys); } public function testImplementsIDelegatedSettings(): void {