Selaa lähdekoodia

Add support for Delegation Settings for more apps

* This adds support for the sharing, groupware, theming and user_ldap
  app
* This adds some code who disapeared during a rebase in the initial
  delegation PR (provisioning_api)

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Carl Schwan 2 vuotta sitten
vanhempi
commit
719dbafd13

+ 2 - 0
apps/dav/lib/Controller/BirthdayCalendarController.php

@@ -88,6 +88,7 @@ class BirthdayCalendarController extends Controller {
 
 	/**
 	 * @return Response
+	 * @AuthorizedAdminSetting(settings=OCA\DAV\Settings\CalDAVSettings)
 	 */
 	public function enable() {
 		$this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'yes');
@@ -104,6 +105,7 @@ class BirthdayCalendarController extends Controller {
 
 	/**
 	 * @return Response
+	 * @AuthorizedAdminSetting(settings=OCA\DAV\Settings\CalDAVSettings)
 	 */
 	public function disable() {
 		$this->config->setAppValue($this->appName, 'generateBirthdayCalendar', 'no');

+ 20 - 9
apps/dav/lib/Settings/CalDAVSettings.php

@@ -29,9 +29,9 @@ use OCA\DAV\AppInfo\Application;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IConfig;
 use OCP\AppFramework\Services\IInitialState;
-use OCP\Settings\ISettings;
+use OCP\Settings\IDelegatedSettings;
 
-class CalDAVSettings implements ISettings {
+class CalDAVSettings implements IDelegatedSettings {
 
 	/** @var IConfig */
 	private $config;
@@ -39,6 +39,13 @@ class CalDAVSettings implements ISettings {
 	/** @var IInitialState */
 	private $initialState;
 
+	private const defaults = [
+		'sendInvitations' => 'yes',
+		'generateBirthdayCalendar' => 'yes',
+		'sendEventReminders' => 'yes',
+		'sendEventRemindersPush' => 'no',
+	];
+
 	/**
 	 * CalDAVSettings constructor.
 	 *
@@ -51,13 +58,7 @@ class CalDAVSettings implements ISettings {
 	}
 
 	public function getForm(): TemplateResponse {
-		$defaults = [
-			'sendInvitations' => 'yes',
-			'generateBirthdayCalendar' => 'yes',
-			'sendEventReminders' => 'yes',
-			'sendEventRemindersPush' => 'no',
-		];
-		foreach ($defaults as $key => $default) {
+		foreach (self::defaults as $key => $default) {
 			$value = $this->config->getAppValue(Application::APP_ID, $key, $default);
 			$this->initialState->provideInitialState($key, $value === 'yes');
 		}
@@ -77,4 +78,14 @@ class CalDAVSettings implements ISettings {
 	public function getPriority() {
 		return 10;
 	}
+
+	public function getName(): ?string {
+		return null; // Only setting in this section
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return [
+			'dav' => ['/(' . implode('|', array_keys(self::defaults)) . ')/']
+		];
+	}
 }

+ 26 - 3
apps/federatedfilesharing/lib/Settings/Admin.php

@@ -27,9 +27,10 @@ namespace OCA\FederatedFileSharing\Settings;
 use OCA\FederatedFileSharing\FederatedShareProvider;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\GlobalScale\IConfig;
-use OCP\Settings\ISettings;
+use OCP\IL10N;
+use OCP\Settings\IDelegatedSettings;
 
-class Admin implements ISettings {
+class Admin implements IDelegatedSettings {
 
 	/** @var FederatedShareProvider */
 	private $fedShareProvider;
@@ -37,15 +38,19 @@ class Admin implements ISettings {
 	/** @var IConfig */
 	private $gsConfig;
 
+	/** @var IL10N */
+	private $l;
+
 	/**
 	 * Admin constructor.
 	 *
 	 * @param FederatedShareProvider $fedShareProvider
 	 * @param IConfig $globalScaleConfig
 	 */
-	public function __construct(FederatedShareProvider $fedShareProvider, IConfig $globalScaleConfig) {
+	public function __construct(FederatedShareProvider $fedShareProvider, IConfig $globalScaleConfig, IL10N $l) {
 		$this->fedShareProvider = $fedShareProvider;
 		$this->gsConfig = $globalScaleConfig;
+		$this->l = $l;
 	}
 
 	/**
@@ -83,4 +88,22 @@ class Admin implements ISettings {
 	public function getPriority() {
 		return 20;
 	}
+
+	public function getName(): ?string {
+		return $this->l->t('Federated Cloud Sharing');
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return [
+			'files_sharing' => [
+				'outgoing_server2server_share_enabled',
+				'incoming_server2server_share_enabled',
+				'federatedGroupSharingSupported',
+				'outgoingServer2serverGroupShareEnabled',
+				'incomingServer2serverGroupShareEnabled',
+				'lookupServerEnabled',
+				'lookupServerUploadEnabled',
+			],
+		];
+	}
 }

+ 3 - 1
apps/federatedfilesharing/tests/Settings/AdminTest.php

@@ -29,6 +29,7 @@ use OCA\FederatedFileSharing\FederatedShareProvider;
 use OCA\FederatedFileSharing\Settings\Admin;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\GlobalScale\IConfig;
+use OCP\IL10N;
 use Test\TestCase;
 
 class AdminTest extends TestCase {
@@ -45,7 +46,8 @@ class AdminTest extends TestCase {
 		$this->gsConfig = $this->createMock(IConfig::class);
 		$this->admin = new Admin(
 			$this->federatedShareProvider,
-			$this->gsConfig
+			$this->gsConfig,
+			$this->createMock(IL10N::class)
 		);
 	}
 

+ 6 - 3
apps/federation/lib/Controller/SettingsController.php

@@ -56,8 +56,9 @@ class SettingsController extends Controller {
 
 
 	/**
-	 * add server to the list of trusted Nextclouds
+	 * Add server to the list of trusted Nextclouds.
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\Federation\Settings\Admin)
 	 * @param string $url
 	 * @return DataResponse
 	 * @throws HintException
@@ -76,8 +77,9 @@ class SettingsController extends Controller {
 	}
 
 	/**
-	 * add server to the list of trusted Nextclouds
+	 * Add server to the list of trusted Nextclouds.
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\Federation\Settings\Admin)
 	 * @param int $id
 	 * @return DataResponse
 	 */
@@ -87,8 +89,9 @@ class SettingsController extends Controller {
 	}
 
 	/**
-	 * check if the server should be added to the list of trusted servers or not
+	 * Check if the server should be added to the list of trusted servers or not.
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\Federation\Settings\Admin)
 	 * @param string $url
 	 * @return bool
 	 * @throws HintException

+ 22 - 3
apps/federation/lib/Settings/Admin.php

@@ -24,15 +24,26 @@ namespace OCA\Federation\Settings;
 
 use OCA\Federation\TrustedServers;
 use OCP\AppFramework\Http\TemplateResponse;
-use OCP\Settings\ISettings;
+use OCP\IL10N;
+use OCP\Settings\IDelegatedSettings;
 
-class Admin implements ISettings {
+class Admin implements IDelegatedSettings {
 
 	/** @var TrustedServers */
 	private $trustedServers;
 
-	public function __construct(TrustedServers $trustedServers) {
+	/** @var IL10N */
+	private $l;
+
+	/**
+	 * Admin constructor.
+	 *
+	 * @param TrustedServers $trustedServers
+	 * @param IL10N $l
+	 */
+	public function __construct(TrustedServers $trustedServers, IL10N $l) {
 		$this->trustedServers = $trustedServers;
+		$this->l = $l;
 	}
 
 	/**
@@ -63,4 +74,12 @@ class Admin implements ISettings {
 	public function getPriority() {
 		return 30;
 	}
+
+	public function getName(): ?string {
+		return $this->l->t("Trusted servers");
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return []; // Handled by custom controller
+	}
 }

+ 3 - 1
apps/federation/tests/Settings/AdminTest.php

@@ -26,6 +26,7 @@ namespace OCA\Federation\Tests\Settings;
 use OCA\Federation\Settings\Admin;
 use OCA\Federation\TrustedServers;
 use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IL10N;
 use Test\TestCase;
 
 class AdminTest extends TestCase {
@@ -38,7 +39,8 @@ class AdminTest extends TestCase {
 		parent::setUp();
 		$this->trustedServers = $this->getMockBuilder('\OCA\Federation\TrustedServers')->disableOriginalConstructor()->getMock();
 		$this->admin = new Admin(
-			$this->trustedServers
+			$this->trustedServers,
+			$this->createMock(IL10N::class)
 		);
 	}
 

+ 65 - 1
apps/provisioning_api/lib/Controller/AppConfigController.php

@@ -26,12 +26,19 @@ declare(strict_types=1);
  */
 namespace OCA\Provisioning_API\Controller;
 
+use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException;
 use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\DataResponse;
 use OCP\AppFramework\OCSController;
 use OCP\IAppConfig;
 use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
 use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Settings\IDelegatedSettings;
+use OCP\Settings\IManager;
 
 class AppConfigController extends OCSController {
 
@@ -41,6 +48,18 @@ class AppConfigController extends OCSController {
 	/** @var IAppConfig */
 	protected $appConfig;
 
+	/** @var IUserSession */
+	private $userSession;
+
+	/** @var IL10N */
+	private $l10n;
+
+	/** @var IGroupManager */
+	private $groupManager;
+
+	/** @var IManager */
+	private $settingManager;
+
 	/**
 	 * @param string $appName
 	 * @param IRequest $request
@@ -50,10 +69,18 @@ class AppConfigController extends OCSController {
 	public function __construct(string $appName,
 								IRequest $request,
 								IConfig $config,
-								IAppConfig $appConfig) {
+								IAppConfig $appConfig,
+								IUserSession $userSession,
+								IL10N $l10n,
+								IGroupManager $groupManager,
+								IManager $settingManager) {
 		parent::__construct($appName, $request);
 		$this->config = $config;
 		$this->appConfig = $appConfig;
+		$this->userSession = $userSession;
+		$this->l10n = $l10n;
+		$this->groupManager = $groupManager;
+		$this->settingManager = $settingManager;
 	}
 
 	/**
@@ -99,12 +126,23 @@ class AppConfigController extends OCSController {
 
 	/**
 	 * @PasswordConfirmationRequired
+	 * @NoSubAdminRequired
+	 * @NoAdminRequired
 	 * @param string $app
 	 * @param string $key
 	 * @param string $value
 	 * @return DataResponse
 	 */
 	public function setValue(string $app, string $key, string $value): DataResponse {
+		$user = $this->userSession->getUser();
+		if ($user === null) {
+			throw new \Exception("User is not logged in."); // Should not happen, since method is guarded by middleware
+		}
+
+		if (!$this->isAllowedToChangedKey($user, $app, $key)) {
+			throw new NotAdminException($this->l10n->t('Logged in user must be an admin or have authorization to edit this setting.'));
+		}
+
 		try {
 			$this->verifyAppId($app);
 			$this->verifyConfigKey($app, $key, $value);
@@ -170,4 +208,30 @@ class AppConfigController extends OCSController {
 			throw new \InvalidArgumentException('The given key can not be set, unlimited quota is forbidden on this instance');
 		}
 	}
+
+	private function isAllowedToChangedKey(IUser $user, string $app, string $key): bool {
+		// Admin right verification
+		$isAdmin = $this->groupManager->isAdmin($user->getUID());
+		if ($isAdmin) {
+			return true;
+		}
+
+		$settings = $this->settingManager->getAllAllowedAdminSettings($user);
+		foreach ($settings as $setting) {
+			if (!($setting instanceof IDelegatedSettings)) {
+				continue;
+			}
+			$allowedKeys = $setting->getAuthorizedAppConfig();
+			if (!array_key_exists($app, $allowedKeys)) {
+				continue;
+			}
+			foreach ($allowedKeys[$app] as $regex) {
+				if ($regex === $key
+					|| (str_starts_with($regex, '/') && preg_match($regex, $key) === 1)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
 }

+ 2 - 1
apps/provisioning_api/lib/Controller/GroupsController.php

@@ -96,9 +96,10 @@ class GroupsController extends AUserData {
 	}
 
 	/**
-	 * returns a list of groups details with ids and displaynames
+	 * Returns a list of groups details with ids and displaynames
 	 *
 	 * @NoAdminRequired
+	 * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Sharing)
 	 *
 	 * @param string $search
 	 * @param int $limit

+ 2 - 1
apps/provisioning_api/lib/Middleware/ProvisioningApiMiddleware.php

@@ -70,7 +70,8 @@ class ProvisioningApiMiddleware extends Middleware {
 	 * @throws NotSubAdminException
 	 */
 	public function beforeController($controller, $methodName) {
-		if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin) {
+		// If AuthorizedAdminSetting, the check will be done in the SecurityMiddleware
+		if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin && !$this->reflector->hasAnnotation('AuthorizedAdminSetting')) {
 			throw new NotSubAdminException();
 		}
 	}

+ 38 - 1
apps/provisioning_api/tests/Controller/AppConfigControllerTest.php

@@ -30,7 +30,12 @@ use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\DataResponse;
 use OCP\IAppConfig;
 use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IL10N;
 use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Settings\IManager;
 use Test\TestCase;
 
 /**
@@ -44,12 +49,24 @@ class AppConfigControllerTest extends TestCase {
 	private $config;
 	/** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */
 	private $appConfig;
+	/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
+	private $userSession;
+	/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
+	private $l10n;
+	/** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
+	private $settingManager;
+	/** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
+	private $groupManager;
 
 	protected function setUp(): void {
 		parent::setUp();
 
 		$this->config = $this->createMock(IConfig::class);
 		$this->appConfig = $this->createMock(IAppConfig::class);
+		$this->userSession = $this->createMock(IUserSession::class);
+		$this->l10n = $this->createMock(IL10N::class);
+		$this->groupManager = $this->createMock(IGroupManager::class);
+		$this->settingManager = $this->createMock(IManager::class);
 	}
 
 	/**
@@ -64,7 +81,11 @@ class AppConfigControllerTest extends TestCase {
 				'provisioning_api',
 				$request,
 				$this->config,
-				$this->appConfig
+				$this->appConfig,
+				$this->userSession,
+				$this->l10n,
+				$this->groupManager,
+				$this->settingManager
 			);
 		} else {
 			return $this->getMockBuilder(AppConfigController::class)
@@ -73,6 +94,10 @@ class AppConfigControllerTest extends TestCase {
 					$request,
 					$this->config,
 					$this->appConfig,
+					$this->userSession,
+					$this->l10n,
+					$this->groupManager,
+					$this->settingManager
 				])
 				->setMethods($methods)
 				->getMock();
@@ -200,6 +225,18 @@ class AppConfigControllerTest extends TestCase {
 	 * @param int $status
 	 */
 	public function testSetValue($app, $key, $value, $appThrows, $keyThrows, $status) {
+		$adminUser = $this->createMock(IUser::class);
+		$adminUser->expects($this->once())
+			->method('getUid')
+			->willReturn('admin');
+
+		$this->userSession->expects($this->once())
+			->method('getUser')
+			->willReturn($adminUser);
+		$this->groupManager->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->willReturn(true);
 		$api = $this->getInstance(['verifyAppId', 'verifyConfigKey']);
 		if ($appThrows instanceof \Exception) {
 			$api->expects($this->once())

+ 24 - 10
apps/provisioning_api/tests/Middleware/ProvisioningApiMiddlewareTest.php

@@ -45,13 +45,20 @@ class ProvisioningApiMiddlewareTest extends TestCase {
 
 	public function dataAnnotation() {
 		return [
-			[false, false, false, false],
-			[false, false,  true, false],
-			[false,  true,  true, false],
-			[ true, false, false,  true],
-			[ true, false,  true, false],
-			[ true,  true, false, false],
-			[ true,  true,  true, false],
+			[false, false, false, false, false],
+			[false, false,  true, false, false],
+			[false,  true,  true, false, false],
+			[ true, false, false, false, true],
+			[ true, false,  true, false, false],
+			[ true,  true, false, false, false],
+			[ true,  true,  true, false, false],
+			[false, false, false, true, false],
+			[false, false,  true, true, false],
+			[false,  true,  true, true, false],
+			[ true, false, false, true, false],
+			[ true, false,  true, true, false],
+			[ true,  true, false, true, false],
+			[ true,  true,  true, true, false],
 		];
 	}
 
@@ -63,7 +70,7 @@ class ProvisioningApiMiddlewareTest extends TestCase {
 	 * @param bool $isSubAdmin
 	 * @param bool $shouldThrowException
 	 */
-	public function testBeforeController($subadminRequired, $isAdmin, $isSubAdmin, $shouldThrowException) {
+	public function testBeforeController($subadminRequired, $isAdmin, $isSubAdmin, $hasSettingAuthorizationAnnotation, $shouldThrowException) {
 		$middleware = new ProvisioningApiMiddleware(
 			$this->reflector,
 			$isAdmin,
@@ -71,8 +78,15 @@ class ProvisioningApiMiddlewareTest extends TestCase {
 		);
 
 		$this->reflector->method('hasAnnotation')
-			->with('NoSubAdminRequired')
-			->willReturn(!$subadminRequired);
+			->willReturnCallback(function ($annotation) use ($subadminRequired, $hasSettingAuthorizationAnnotation) {
+				if ($annotation === 'NoSubAdminRequired') {
+					return !$subadminRequired;
+				}
+				if ($annotation === 'AuthorizedAdminSetting') {
+					return $hasSettingAuthorizationAnnotation;
+				}
+				return false;
+			});
 
 		try {
 			$middleware->beforeController(

+ 18 - 3
apps/sharebymail/lib/Settings/Admin.php

@@ -24,15 +24,20 @@
 namespace OCA\ShareByMail\Settings;
 
 use OCP\AppFramework\Http\TemplateResponse;
-use OCP\Settings\ISettings;
+use OCP\IL10N;
+use OCP\Settings\IDelegatedSettings;
 
-class Admin implements ISettings {
+class Admin implements IDelegatedSettings {
 
 	/** @var SettingsManager */
 	private $settingsManager;
 
-	public function __construct(SettingsManager $settingsManager) {
+	/** @var IL10N */
+	private $l;
+
+	public function __construct(SettingsManager $settingsManager, IL10N $l) {
 		$this->settingsManager = $settingsManager;
+		$this->l = $l;
 	}
 
 	/**
@@ -64,4 +69,14 @@ class Admin implements ISettings {
 	public function getPriority() {
 		return 40;
 	}
+
+	public function getName(): ?string {
+		return $this->l->t('Share by mail');
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return [
+			'sharebymail' => ['s/(sendpasswordmail|replyToInitiator)/'],
+		];
+	}
 }

+ 3 - 0
apps/theming/lib/Controller/ThemingController.php

@@ -124,6 +124,7 @@ class ThemingController extends Controller {
 	}
 
 	/**
+	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
 	 * @param string $setting
 	 * @param string $value
 	 * @return DataResponse
@@ -208,6 +209,7 @@ class ThemingController extends Controller {
 	}
 
 	/**
+	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
 	 * @return DataResponse
 	 * @throws NotPermittedException
 	 */
@@ -278,6 +280,7 @@ class ThemingController extends Controller {
 
 	/**
 	 * Revert setting to default value
+	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
 	 *
 	 * @param string $setting setting which should be reverted
 	 * @return DataResponse

+ 12 - 2
apps/theming/lib/Settings/Admin.php

@@ -33,9 +33,9 @@ use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IConfig;
 use OCP\IL10N;
 use OCP\IURLGenerator;
-use OCP\Settings\ISettings;
+use OCP\Settings\IDelegatedSettings;
 
-class Admin implements ISettings {
+class Admin implements IDelegatedSettings {
 	/** @var IConfig */
 	private $config;
 	/** @var IL10N */
@@ -106,4 +106,14 @@ class Admin implements ISettings {
 	public function getPriority(): int {
 		return 5;
 	}
+
+	public function getName(): ?string {
+		return null; // Only one setting in this section
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return [
+			'theming' => '/.*/',
+		];
+	}
 }

+ 9 - 4
apps/user_ldap/lib/Controller/ConfigAPIController.php

@@ -76,7 +76,7 @@ class ConfigAPIController extends OCSController {
 	}
 
 	/**
-	 * creates a new (empty) configuration and returns the resulting prefix
+	 * Creates a new (empty) configuration and returns the resulting prefix
 	 *
 	 * Example: curl -X POST -H "OCS-APIREQUEST: true"  -u $admin:$password \
 	 *   https://nextcloud.server/ocs/v2.php/apps/user_ldap/api/v1/config
@@ -110,6 +110,7 @@ class ConfigAPIController extends OCSController {
 	 *
 	 * For JSON output provide the format=json parameter
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\User_LDAP\Settings\Admin)
 	 * @return DataResponse
 	 * @throws OCSException
 	 */
@@ -142,6 +143,7 @@ class ConfigAPIController extends OCSController {
 	 *   <data/>
 	 * </ocs>
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\User_LDAP\Settings\Admin)
 	 * @param string $configID
 	 * @return DataResponse
 	 * @throws OCSBadRequestException
@@ -164,7 +166,7 @@ class ConfigAPIController extends OCSController {
 	}
 
 	/**
-	 * modifies a configuration
+	 * Modifies a configuration
 	 *
 	 * Example:
 	 *   curl -X PUT -d "configData[ldapHost]=ldaps://my.ldap.server&configData[ldapPort]=636" \
@@ -181,6 +183,7 @@ class ConfigAPIController extends OCSController {
 	 *   <data/>
 	 * </ocs>
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\User_LDAP\Settings\Admin)
 	 * @param string $configID
 	 * @param array $configData
 	 * @return DataResponse
@@ -216,7 +219,7 @@ class ConfigAPIController extends OCSController {
 	}
 
 	/**
-	 * retrieves a configuration
+	 * Retrieves a configuration
 	 *
 	 * <?xml version="1.0"?>
 	 * <ocs>
@@ -280,6 +283,7 @@ class ConfigAPIController extends OCSController {
 	 *   </data>
 	 * </ocs>
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\User_LDAP\Settings\Admin)
 	 * @param string $configID
 	 * @param bool|string $showPassword
 	 * @return DataResponse
@@ -311,8 +315,9 @@ class ConfigAPIController extends OCSController {
 	}
 
 	/**
-	 * if the given config ID is not available, an exception is thrown
+	 * If the given config ID is not available, an exception is thrown
 	 *
+	 * @AuthorizedAdminSetting(settings=OCA\User_LDAP\Settings\Admin)
 	 * @param string $configID
 	 * @throws OCSNotFoundException
 	 */

+ 10 - 2
apps/user_ldap/lib/Settings/Admin.php

@@ -29,10 +29,10 @@ use OCA\User_LDAP\Configuration;
 use OCA\User_LDAP\Helper;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\IL10N;
-use OCP\Settings\ISettings;
+use OCP\Settings\IDelegatedSettings;
 use OCP\Template;
 
-class Admin implements ISettings {
+class Admin implements IDelegatedSettings {
 	/** @var IL10N */
 	private $l;
 
@@ -98,4 +98,12 @@ class Admin implements ISettings {
 	public function getPriority() {
 		return 5;
 	}
+
+	public function getName(): ?string {
+		return null; // Only one setting in this section
+	}
+
+	public function getAuthorizedAppConfig(): array {
+		return []; // Custom controller
+	}
 }