Merge pull request #15679 from nextcloud/feature/sub-admin-settings

Make it possible to show admin settings for sub admins
This commit is contained in:
Roeland Jago Douma 2019-05-24 15:37:46 +02:00 committed by GitHub
commit 5b0e70ff77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 271 additions and 52 deletions

View File

@ -379,6 +379,7 @@ return array(
'OCP\\Settings\\IManager' => $baseDir . '/lib/public/Settings/IManager.php', 'OCP\\Settings\\IManager' => $baseDir . '/lib/public/Settings/IManager.php',
'OCP\\Settings\\ISection' => $baseDir . '/lib/public/Settings/ISection.php', 'OCP\\Settings\\ISection' => $baseDir . '/lib/public/Settings/ISection.php',
'OCP\\Settings\\ISettings' => $baseDir . '/lib/public/Settings/ISettings.php', 'OCP\\Settings\\ISettings' => $baseDir . '/lib/public/Settings/ISettings.php',
'OCP\\Settings\\ISubAdminSettings' => $baseDir . '/lib/public/Settings/ISubAdminSettings.php',
'OCP\\Share' => $baseDir . '/lib/public/Share.php', 'OCP\\Share' => $baseDir . '/lib/public/Share.php',
'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php', 'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php', 'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',

View File

@ -409,6 +409,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Settings\\IManager' => __DIR__ . '/../../..' . '/lib/public/Settings/IManager.php', 'OCP\\Settings\\IManager' => __DIR__ . '/../../..' . '/lib/public/Settings/IManager.php',
'OCP\\Settings\\ISection' => __DIR__ . '/../../..' . '/lib/public/Settings/ISection.php', 'OCP\\Settings\\ISection' => __DIR__ . '/../../..' . '/lib/public/Settings/ISection.php',
'OCP\\Settings\\ISettings' => __DIR__ . '/../../..' . '/lib/public/Settings/ISettings.php', 'OCP\\Settings\\ISettings' => __DIR__ . '/../../..' . '/lib/public/Settings/ISettings.php',
'OCP\\Settings\\ISubAdminSettings' => __DIR__ . '/../../..' . '/lib/public/Settings/ISubAdminSettings.php',
'OCP\\Share' => __DIR__ . '/../../..' . '/lib/public/Share.php', 'OCP\\Share' => __DIR__ . '/../../..' . '/lib/public/Share.php',
'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php', 'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php',
'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php', 'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php',

View File

@ -56,6 +56,7 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\Folder; use OCP\Files\Folder;
use OCP\Files\IAppData; use OCP\Files\IAppData;
use OCP\GlobalScale\IConfig; use OCP\GlobalScale\IConfig;
use OCP\Group\ISubAdmin;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
use OCP\INavigationManager; use OCP\INavigationManager;
@ -218,6 +219,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$c['AppName'], $c['AppName'],
$server->getUserSession()->isLoggedIn(), $server->getUserSession()->isLoggedIn(),
$server->getGroupManager()->isAdmin($this->getUserId()), $server->getGroupManager()->isAdmin($this->getUserId()),
$server->getUserSession()->getUser() !== null && $server->query(ISubAdmin::class)->isSubAdmin($server->getUserSession()->getUser()),
$server->getContentSecurityPolicyManager(), $server->getContentSecurityPolicyManager(),
$server->getCsrfTokenManager(), $server->getCsrfTokenManager(),
$server->getContentSecurityPolicyNonceManager(), $server->getContentSecurityPolicyNonceManager(),

View File

@ -82,6 +82,8 @@ class SecurityMiddleware extends Middleware {
private $isLoggedIn; private $isLoggedIn;
/** @var bool */ /** @var bool */
private $isAdminUser; private $isAdminUser;
/** @var bool */
private $isSubAdmin;
/** @var ContentSecurityPolicyManager */ /** @var ContentSecurityPolicyManager */
private $contentSecurityPolicyManager; private $contentSecurityPolicyManager;
/** @var CsrfTokenManager */ /** @var CsrfTokenManager */
@ -101,6 +103,7 @@ class SecurityMiddleware extends Middleware {
string $appName, string $appName,
bool $isLoggedIn, bool $isLoggedIn,
bool $isAdminUser, bool $isAdminUser,
bool $isSubAdmin,
ContentSecurityPolicyManager $contentSecurityPolicyManager, ContentSecurityPolicyManager $contentSecurityPolicyManager,
CsrfTokenManager $csrfTokenManager, CsrfTokenManager $csrfTokenManager,
ContentSecurityPolicyNonceManager $cspNonceManager, ContentSecurityPolicyNonceManager $cspNonceManager,
@ -115,6 +118,7 @@ class SecurityMiddleware extends Middleware {
$this->logger = $logger; $this->logger = $logger;
$this->isLoggedIn = $isLoggedIn; $this->isLoggedIn = $isLoggedIn;
$this->isAdminUser = $isAdminUser; $this->isAdminUser = $isAdminUser;
$this->isSubAdmin = $isSubAdmin;
$this->contentSecurityPolicyManager = $contentSecurityPolicyManager; $this->contentSecurityPolicyManager = $contentSecurityPolicyManager;
$this->csrfTokenManager = $csrfTokenManager; $this->csrfTokenManager = $csrfTokenManager;
$this->cspNonceManager = $cspNonceManager; $this->cspNonceManager = $cspNonceManager;
@ -143,7 +147,14 @@ class SecurityMiddleware extends Middleware {
throw new NotLoggedInException(); throw new NotLoggedInException();
} }
if(!$this->reflector->hasAnnotation('NoAdminRequired') && !$this->isAdminUser) { if($this->reflector->hasAnnotation('SubAdminRequired')
&& !$this->isSubAdmin
&& !$this->isAdminUser) {
throw new NotAdminException($this->l10n->t('Logged in user must be an admin or sub admin'));
}
if(!$this->reflector->hasAnnotation('SubAdminRequired')
&& !$this->reflector->hasAnnotation('NoAdminRequired')
&& !$this->isAdminUser) {
throw new NotAdminException($this->l10n->t('Logged in user must be an admin')); throw new NotAdminException($this->l10n->t('Logged in user must be an admin'));
} }
} }

View File

@ -29,6 +29,7 @@
namespace OC\Settings; namespace OC\Settings;
use Closure;
use OCP\AppFramework\QueryException; use OCP\AppFramework\QueryException;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger; use OCP\ILogger;
@ -38,6 +39,7 @@ use OCP\L10N\IFactory;
use OCP\Settings\ISettings; use OCP\Settings\ISettings;
use OCP\Settings\IManager; use OCP\Settings\IManager;
use OCP\Settings\ISection; use OCP\Settings\ISection;
use OCP\Settings\ISubAdminSettings;
class Manager implements IManager { class Manager implements IManager {
@ -150,10 +152,11 @@ class Manager implements IManager {
/** /**
* @param string $type 'admin' or 'personal' * @param string $type 'admin' or 'personal'
* @param string $section * @param string $section
* @param Closure $filter optional filter to apply on all loaded ISettings
* *
* @return ISettings[] * @return ISettings[]
*/ */
protected function getSettings(string $type, string $section): array { protected function getSettings(string $type, string $section, Closure $filter = null): array {
if (!isset($this->settings[$type])) { if (!isset($this->settings[$type])) {
$this->settings[$type] = []; $this->settings[$type] = [];
} }
@ -162,6 +165,10 @@ class Manager implements IManager {
} }
foreach ($this->settingClasses as $class => $settingsType) { foreach ($this->settingClasses as $class => $settingsType) {
if ($type !== $settingsType) {
continue;
}
try { try {
/** @var ISettings $setting */ /** @var ISettings $setting */
$setting = \OC::$server->query($class); $setting = \OC::$server->query($class);
@ -175,6 +182,9 @@ class Manager implements IManager {
continue; continue;
} }
if ($filter !== null && !$filter($setting)) {
continue;
}
if ($setting->getSection() === null) { if ($setting->getSection() === null) {
continue; continue;
} }
@ -226,33 +236,44 @@ class Manager implements IManager {
/** /**
* @param string $section * @param string $section
* @param Closure $filter
* *
* @return ISection[] * @return ISection[]
*/ */
private function getBuiltInAdminSettings($section): array { private function getBuiltInAdminSettings($section, Closure $filter = null): array {
$forms = []; $forms = [];
if ($section === 'overview') { if ($section === 'overview') {
/** @var ISettings $form */ /** @var ISettings $form */
$form = $this->container->query(Admin\Overview::class); $form = $this->container->query(Admin\Overview::class);
$forms[$form->getPriority()] = [$form]; if ($filter === null || $filter($form)) {
$forms[$form->getPriority()] = [$form];
}
} }
if ($section === 'server') { if ($section === 'server') {
/** @var ISettings $form */ /** @var ISettings $form */
$form = $this->container->query(Admin\Server::class); $form = $this->container->query(Admin\Server::class);
$forms[$form->getPriority()] = [$form]; if ($filter === null || $filter($form)) {
$forms[$form->getPriority()] = [$form];
}
$form = $this->container->query(Admin\Mail::class); $form = $this->container->query(Admin\Mail::class);
$forms[$form->getPriority()] = [$form]; if ($filter === null || $filter($form)) {
$forms[$form->getPriority()] = [$form];
}
} }
if ($section === 'security') { if ($section === 'security') {
/** @var ISettings $form */ /** @var ISettings $form */
$form = $this->container->query(Admin\Security::class); $form = $this->container->query(Admin\Security::class);
$forms[$form->getPriority()] = [$form]; if ($filter === null || $filter($form)) {
$forms[$form->getPriority()] = [$form];
}
} }
if ($section === 'sharing') { if ($section === 'sharing') {
/** @var ISettings $form */ /** @var ISettings $form */
$form = $this->container->query(Admin\Sharing::class); $form = $this->container->query(Admin\Sharing::class);
$forms[$form->getPriority()] = [$form]; if ($filter === null || $filter($form)) {
$forms[$form->getPriority()] = [$form];
}
} }
return $forms; return $forms;
@ -290,9 +311,17 @@ class Manager implements IManager {
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function getAdminSettings($section): array { public function getAdminSettings($section, bool $subAdminOnly = false): array {
$settings = $this->getBuiltInAdminSettings($section); if ($subAdminOnly) {
$appSettings = $this->getSettings('admin', $section); $subAdminSettingsFilter = function(ISettings $settings) {
return $settings instanceof ISubAdminSettings;
};
$settings = $this->getBuiltInAdminSettings($section, $subAdminSettingsFilter);
$appSettings = $this->getSettings('admin', $section, $subAdminSettingsFilter);
} else {
$settings = $this->getBuiltInAdminSettings($section);
$appSettings = $this->getSettings('admin', $section);
}
foreach ($appSettings as $setting) { foreach ($appSettings as $setting) {
if (!isset($settings[$setting->getPriority()])) { if (!isset($settings[$setting->getPriority()])) {

View File

@ -82,10 +82,11 @@ interface IManager {
* returns a list of the admin settings * returns a list of the admin settings
* *
* @param string $section the section id for which to load the settings * @param string $section the section id for which to load the settings
* @param bool $subAdminOnly only return settings sub admins are supposed to see (since 17.0.0)
* @return array array of IAdmin[] where key is the priority * @return array array of IAdmin[] where key is the priority
* @since 9.1.0 * @since 9.1.0
*/ */
public function getAdminSettings($section): array; public function getAdminSettings($section, bool $subAdminOnly = false): array;
/** /**
* returns a list of the personal settings * returns a list of the personal settings

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/**
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @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/>.
*/
namespace OCP\Settings;
/**
* Tagging interface for settings that should be shown to sub admins
*
* @since 17.0.0
*/
interface ISubAdminSettings extends ISettings {
}

View File

@ -27,8 +27,12 @@ namespace OC\Settings\Controller;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\Group\ISubAdmin;
use OCP\IGroupManager;
use OCP\INavigationManager; use OCP\INavigationManager;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Settings\IManager as ISettingsManager; use OCP\Settings\IManager as ISettingsManager;
use OCP\Template; use OCP\Template;
@ -38,21 +42,21 @@ use OCP\Template;
class AdminSettingsController extends Controller { class AdminSettingsController extends Controller {
use CommonSettingsTrait; use CommonSettingsTrait;
/**
* @param string $appName
* @param IRequest $request
* @param INavigationManager $navigationManager
* @param ISettingsManager $settingsManager
*/
public function __construct( public function __construct(
$appName, $appName,
IRequest $request, IRequest $request,
INavigationManager $navigationManager, INavigationManager $navigationManager,
ISettingsManager $settingsManager ISettingsManager $settingsManager,
IUserSession $userSession,
IGroupManager $groupManager,
ISubAdmin $subAdmin
) { ) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->navigationManager = $navigationManager; $this->navigationManager = $navigationManager;
$this->settingsManager = $settingsManager; $this->settingsManager = $settingsManager;
$this->userSession = $userSession;
$this->groupManager = $groupManager;
$this->subAdmin = $subAdmin;
} }
/** /**
@ -60,6 +64,7 @@ class AdminSettingsController extends Controller {
* @return TemplateResponse * @return TemplateResponse
* *
* @NoCSRFRequired * @NoCSRFRequired
* @SubAdminRequired
*/ */
public function index($section) { public function index($section) {
return $this->getIndexResponse('admin', $section); return $this->getIndexResponse('admin', $section);
@ -70,9 +75,16 @@ class AdminSettingsController extends Controller {
* @return array * @return array
*/ */
protected function getSettings($section) { protected function getSettings($section) {
$settings = $this->settingsManager->getAdminSettings($section); /** @var IUser $user */
$user = $this->userSession->getUser();
$isSubAdmin = !$this->groupManager->isAdmin($user->getUID()) && $this->subAdmin->isSubAdmin($user);
$settings = $this->settingsManager->getAdminSettings(
$section,
$isSubAdmin
);
$formatted = $this->formatSettings($settings); $formatted = $this->formatSettings($settings);
if($section === 'additional') { // Do not show legacy forms for sub admins
if($section === 'additional' && !$isSubAdmin) {
$formatted['content'] .= $this->getLegacyForms(); $formatted['content'] .= $this->getLegacyForms();
} }
return $formatted; return $formatted;

View File

@ -25,18 +25,32 @@
namespace OC\Settings\Controller; namespace OC\Settings\Controller;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\Group\ISubAdmin;
use OCP\IGroupManager;
use OCP\INavigationManager; use OCP\INavigationManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Settings\IManager as ISettingsManager; use OCP\Settings\IManager as ISettingsManager;
use OCP\Settings\IIconSection; use OCP\Settings\IIconSection;
use OCP\Settings\ISettings; use OCP\Settings\ISettings;
trait CommonSettingsTrait { trait CommonSettingsTrait {
/** @var ISettingsManager */ /** @var ISettingsManager */
private $settingsManager; private $settingsManager;
/** @var INavigationManager */ /** @var INavigationManager */
private $navigationManager; private $navigationManager;
/** @var IUserSession */
private $userSession;
/** @var IGroupManager */
private $groupManager;
/** @var ISubAdmin */
private $subAdmin;
/** /**
* @param string $currentSection * @param string $currentSection
* @return array * @return array
@ -47,8 +61,16 @@ trait CommonSettingsTrait {
'admin' => [] 'admin' => []
]; ];
if(\OC_User::isAdminUser(\OC_User::getUser())) { /** @var IUser $user */
$templateParameters['admin'] = $this->formatAdminSections($currentType, $currentSection); $user = $this->userSession->getUser();
$isAdmin = $this->groupManager->isAdmin($user->getUID());
$isSubAdmin = $this->subAdmin->isSubAdmin($user);
if ($isAdmin || $isSubAdmin) {
$templateParameters['admin'] = $this->formatAdminSections(
$currentType,
$currentSection,
!$isAdmin && $isSubAdmin
);
} }
return [ return [
@ -56,13 +78,13 @@ trait CommonSettingsTrait {
]; ];
} }
protected function formatSections($sections, $currentSection, $type, $currentType) { protected function formatSections($sections, $currentSection, $type, $currentType, bool $subAdminOnly = false) {
$templateParameters = []; $templateParameters = [];
/** @var \OCP\Settings\ISection[] $prioritizedSections */ /** @var \OCP\Settings\ISection[] $prioritizedSections */
foreach($sections as $prioritizedSections) { foreach($sections as $prioritizedSections) {
foreach ($prioritizedSections as $section) { foreach ($prioritizedSections as $section) {
if($type === 'admin') { if($type === 'admin') {
$settings = $this->settingsManager->getAdminSettings($section->getID()); $settings = $this->settingsManager->getAdminSettings($section->getID(), $subAdminOnly);
} else if($type === 'personal') { } else if($type === 'personal') {
$settings = $this->settingsManager->getPersonalSettings($section->getID()); $settings = $this->settingsManager->getPersonalSettings($section->getID());
} }
@ -96,9 +118,9 @@ trait CommonSettingsTrait {
return $templateParameters; return $templateParameters;
} }
protected function formatAdminSections($currentType, $currentSections) { protected function formatAdminSections($currentType, $currentSections, bool $subAdminOnly) {
$sections = $this->settingsManager->getAdminSections(); $sections = $this->settingsManager->getAdminSections();
$templateParameters = $this->formatSections($sections, $currentSections, 'admin', $currentType); $templateParameters = $this->formatSections($sections, $currentSections, 'admin', $currentType, $subAdminOnly);
return $templateParameters; return $templateParameters;
} }

View File

@ -26,8 +26,11 @@ namespace OC\Settings\Controller;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\Group\ISubAdmin;
use OCP\IGroupManager;
use OCP\INavigationManager; use OCP\INavigationManager;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUserSession;
use OCP\Settings\IManager as ISettingsManager; use OCP\Settings\IManager as ISettingsManager;
use OCP\Template; use OCP\Template;
@ -38,11 +41,17 @@ class PersonalSettingsController extends Controller {
$appName, $appName,
IRequest $request, IRequest $request,
INavigationManager $navigationManager, INavigationManager $navigationManager,
ISettingsManager $settingsManager ISettingsManager $settingsManager,
IUserSession $userSession,
IGroupManager $groupManager,
ISubAdmin $subAdmin
) { ) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->navigationManager = $navigationManager; $this->navigationManager = $navigationManager;
$this->settingsManager = $settingsManager; $this->settingsManager = $settingsManager;
$this->userSession = $userSession;
$this->subAdmin = $subAdmin;
$this->groupManager = $groupManager;
} }
/** /**

View File

@ -25,9 +25,14 @@ namespace Tests\Settings\Controller;
use OC\Settings\Personal\ServerDevNotice; use OC\Settings\Personal\ServerDevNotice;
use OC\Settings\Controller\AdminSettingsController; use OC\Settings\Controller\AdminSettingsController;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\Group\ISubAdmin;
use OCP\IGroupManager;
use OCP\INavigationManager; use OCP\INavigationManager;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Settings\IManager; use OCP\Settings\IManager;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase; use Test\TestCase;
/** /**
@ -38,29 +43,42 @@ use Test\TestCase;
* @package Tests\Settings\Controller * @package Tests\Settings\Controller
*/ */
class AdminSettingsControllerTest extends TestCase { class AdminSettingsControllerTest extends TestCase {
/** @var AdminSettingsController */ /** @var AdminSettingsController */
private $adminSettingsController; private $adminSettingsController;
/** @var IRequest */ /** @var IRequest|MockObject */
private $request; private $request;
/** @var INavigationManager */ /** @var INavigationManager|MockObject */
private $navigationManager; private $navigationManager;
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ /** @var IManager|MockObject */
private $settingsManager; private $settingsManager;
/** @var IUserSession|MockObject */
private $userSession;
/** @var IGroupManager|MockObject */
private $groupManager;
/** @var ISubAdmin|MockObject */
private $subAdmin;
/** @var string */ /** @var string */
private $adminUid = 'lololo'; private $adminUid = 'lololo';
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->request = $this->getMockBuilder(IRequest::class)->getMock(); $this->request = $this->createMock(IRequest::class);
$this->navigationManager = $this->getMockBuilder(INavigationManager::class)->getMock(); $this->navigationManager = $this->createMock(INavigationManager::class);
$this->settingsManager = $this->getMockBuilder(IManager::class)->getMock(); $this->settingsManager = $this->createMock(IManager::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->subAdmin = $this->createMock(ISubAdmin::class);
$this->adminSettingsController = new AdminSettingsController( $this->adminSettingsController = new AdminSettingsController(
'settings', 'settings',
$this->request, $this->request,
$this->navigationManager, $this->navigationManager,
$this->settingsManager $this->settingsManager,
$this->userSession,
$this->groupManager,
$this->subAdmin
); );
$user = \OC::$server->getUserManager()->createUser($this->adminUid, 'olo'); $user = \OC::$server->getUserManager()->createUser($this->adminUid, 'olo');
@ -75,6 +93,19 @@ class AdminSettingsControllerTest extends TestCase {
} }
public function testIndex() { public function testIndex() {
$user = $this->createMock(IUser::class);
$this->userSession
->method('getUser')
->willReturn($user);
$user->method('getUID')->willReturn('user123');
$this->groupManager
->method('isAdmin')
->with('user123')
->willReturn(true);
$this->subAdmin
->method('isSubAdmin')
->with($user)
->willReturn(false);
$this->settingsManager $this->settingsManager
->expects($this->once()) ->expects($this->once())
->method('getAdminSections') ->method('getAdminSections')
@ -89,7 +120,9 @@ class AdminSettingsControllerTest extends TestCase {
->with('test') ->with('test')
->willReturn([5 => new ServerDevNotice()]); ->willReturn([5 => new ServerDevNotice()]);
$idx = $this->adminSettingsController->index('test');
$expected = new TemplateResponse('settings', 'settings/frame', ['forms' => ['personal' => [], 'admin' => []], 'content' => '']); $expected = new TemplateResponse('settings', 'settings/frame', ['forms' => ['personal' => [], 'admin' => []], 'content' => '']);
$this->assertEquals($expected, $this->adminSettingsController->index('test')); $this->assertEquals($expected, $idx);
} }
} }

View File

@ -96,12 +96,12 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->csrfTokenManager = $this->createMock(CsrfTokenManager::class); $this->csrfTokenManager = $this->createMock(CsrfTokenManager::class);
$this->cspNonceManager = $this->createMock(ContentSecurityPolicyNonceManager::class); $this->cspNonceManager = $this->createMock(ContentSecurityPolicyNonceManager::class);
$this->l10n = $this->createMock(IL10N::class); $this->l10n = $this->createMock(IL10N::class);
$this->middleware = $this->getMiddleware(true, true); $this->middleware = $this->getMiddleware(true, true, false);
$this->secException = new SecurityException('hey', false); $this->secException = new SecurityException('hey', false);
$this->secAjaxException = new SecurityException('hey', true); $this->secAjaxException = new SecurityException('hey', true);
} }
private function getMiddleware(bool $isLoggedIn, bool $isAdminUser, bool $isAppEnabledForUser = true): SecurityMiddleware { private function getMiddleware(bool $isLoggedIn, bool $isAdminUser, bool $isSubAdmin, bool $isAppEnabledForUser = true): SecurityMiddleware {
$this->appManager = $this->createMock(IAppManager::class); $this->appManager = $this->createMock(IAppManager::class);
$this->appManager->expects($this->any()) $this->appManager->expects($this->any())
@ -117,6 +117,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
'files', 'files',
$isLoggedIn, $isLoggedIn,
$isAdminUser, $isAdminUser,
$isSubAdmin,
$this->contentSecurityPolicyManager, $this->contentSecurityPolicyManager,
$this->csrfTokenManager, $this->csrfTokenManager,
$this->cspNonceManager, $this->cspNonceManager,
@ -153,7 +154,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$isLoggedIn = true; $isLoggedIn = true;
} }
$sec = $this->getMiddleware($isLoggedIn, $isAdminUser); $sec = $this->getMiddleware($isLoggedIn, $isAdminUser, false);
try { try {
$this->reader->reflect(__CLASS__, $method); $this->reader->reflect(__CLASS__, $method);
@ -214,11 +215,6 @@ class SecurityMiddlewareTest extends \Test\TestCase {
'isAdminUser', 'isAdminUser',
0 0
); );
$this->ajaxExceptionStatus(
__FUNCTION__,
'isSubAdminUser',
0
);
$this->ajaxExceptionStatus( $this->ajaxExceptionStatus(
__FUNCTION__, __FUNCTION__,
'passesCSRFCheck', 'passesCSRFCheck',
@ -236,7 +232,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
->method('passesCSRFCheck') ->method('passesCSRFCheck')
->will($this->returnValue(false)); ->will($this->returnValue(false));
$sec = $this->getMiddleware(false, false); $sec = $this->getMiddleware(false, false, false);
$this->reader->reflect(__CLASS__, __FUNCTION__); $this->reader->reflect(__CLASS__, __FUNCTION__);
$sec->beforeController($this->controller, __FUNCTION__); $sec->beforeController($this->controller, __FUNCTION__);
@ -257,7 +253,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$isAdminUser = false; $isAdminUser = false;
} }
$sec = $this->getMiddleware($isLoggedIn, $isAdminUser); $sec = $this->getMiddleware($isLoggedIn, $isAdminUser, false);
if($shouldFail) { if($shouldFail) {
$this->expectException(SecurityException::class); $this->expectException(SecurityException::class);
@ -452,6 +448,41 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->securityCheck(__FUNCTION__, 'isAdminUser'); $this->securityCheck(__FUNCTION__, 'isAdminUser');
} }
/**
* @NoCSRFRequired
* @SubAdminRequired
*/
public function testIsNotSubAdminCheck(){
$this->reader->reflect(__CLASS__,__FUNCTION__);
$sec = $this->getMiddleware(true, false, false);
$this->expectException(SecurityException::class);
$sec->beforeController($this, __METHOD__);
}
/**
* @NoCSRFRequired
* @SubAdminRequired
*/
public function testIsSubAdminCheck(){
$this->reader->reflect(__CLASS__,__FUNCTION__);
$sec = $this->getMiddleware(true, false, true);
$sec->beforeController($this, __METHOD__);
$this->addToAssertionCount(1);
}
/**
* @NoCSRFRequired
* @SubAdminRequired
*/
public function testIsSubAdminAndAdminCheck(){
$this->reader->reflect(__CLASS__,__FUNCTION__);
$sec = $this->getMiddleware(true, true, true);
$sec->beforeController($this, __METHOD__);
$this->addToAssertionCount(1);
}
/** /**
* @NoCSRFRequired * @NoCSRFRequired
@ -479,7 +510,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->createMock(ISecureRandom::class), $this->createMock(ISecureRandom::class),
$this->createMock(IConfig::class) $this->createMock(IConfig::class)
); );
$this->middleware = $this->getMiddleware(false, false); $this->middleware = $this->getMiddleware(false, false, false);
$this->urlGenerator $this->urlGenerator
->expects($this->once()) ->expects($this->once())
->method('linkToRoute') ->method('linkToRoute')
@ -514,7 +545,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->createMock(IConfig::class) $this->createMock(IConfig::class)
); );
$this->middleware = $this->getMiddleware(false, false); $this->middleware = $this->getMiddleware(false, false, false);
$response = $this->middleware->afterException( $response = $this->middleware->afterException(
$this->controller, $this->controller,
'test', 'test',
@ -559,7 +590,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
$this->createMock(ISecureRandom::class), $this->createMock(ISecureRandom::class),
$this->createMock(IConfig::class) $this->createMock(IConfig::class)
); );
$this->middleware = $this->getMiddleware(false, false); $this->middleware = $this->getMiddleware(false, false, false);
$this->logger $this->logger
->expects($this->once()) ->expects($this->once())
->method('logException'); ->method('logException');
@ -684,7 +715,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function testRestrictedAppLoggedInPublicPage() { public function testRestrictedAppLoggedInPublicPage() {
$middleware = $this->getMiddleware(true, false); $middleware = $this->getMiddleware(true, false, false);
$this->reader->reflect(__CLASS__,__FUNCTION__); $this->reader->reflect(__CLASS__,__FUNCTION__);
$this->appManager->method('getAppPath') $this->appManager->method('getAppPath')
@ -705,7 +736,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function testRestrictedAppNotLoggedInPublicPage() { public function testRestrictedAppNotLoggedInPublicPage() {
$middleware = $this->getMiddleware(false, false); $middleware = $this->getMiddleware(false, false, false);
$this->reader->reflect(__CLASS__,__FUNCTION__); $this->reader->reflect(__CLASS__,__FUNCTION__);
$this->appManager->method('getAppPath') $this->appManager->method('getAppPath')
@ -725,7 +756,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function testRestrictedAppLoggedIn() { public function testRestrictedAppLoggedIn() {
$middleware = $this->getMiddleware(true, false, false); $middleware = $this->getMiddleware(true, false, false, false);
$this->reader->reflect(__CLASS__,__FUNCTION__); $this->reader->reflect(__CLASS__,__FUNCTION__);
$this->appManager->method('getAppPath') $this->appManager->method('getAppPath')

View File

@ -23,6 +23,7 @@
namespace Tests\Settings; namespace Tests\Settings;
use function get_class;
use OC\Settings\Admin\Sharing; use OC\Settings\Admin\Sharing;
use OC\Settings\Manager; use OC\Settings\Manager;
use OC\Settings\Mapper; use OC\Settings\Mapper;
@ -34,6 +35,8 @@ use OCP\ILogger;
use OCP\IServerContainer; use OCP\IServerContainer;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCP\L10N\IFactory; use OCP\L10N\IFactory;
use OCP\Settings\ISettings;
use OCP\Settings\ISubAdminSettings;
use Test\TestCase; use Test\TestCase;
class ManagerTest extends TestCase { class ManagerTest extends TestCase {
@ -207,6 +210,35 @@ class ManagerTest extends TestCase {
], $settings); ], $settings);
} }
public function testGetAdminSettingsAsSubAdmin() {
$section = $this->createMock(Sharing::class);
$this->container->expects($this->once())
->method('query')
->with(Sharing::class)
->willReturn($section);
$settings = $this->manager->getAdminSettings('sharing', true);
$this->assertEquals([], $settings);
}
public function testGetSubAdminSettingsAsSubAdmin() {
$section = $this->createMock(ISubAdminSettings::class);
$section->expects($this->once())
->method('getPriority')
->willReturn(13);
$this->container->expects($this->once())
->method('query')
->with(Sharing::class)
->willReturn($section);
$settings = $this->manager->getAdminSettings('sharing', true);
$this->assertEquals([
13 => [$section]
], $settings);
}
public function testGetPersonalSettings() { public function testGetPersonalSettings() {
$section = $this->createMock(Security::class); $section = $this->createMock(Security::class);
$section->expects($this->once()) $section->expects($this->once())