Merge pull request #4890 from nextcloud/unify-settings

Unify settings
This commit is contained in:
blizzz 2017-06-29 20:02:09 +02:00 committed by GitHub
commit 72d3bfcf56
71 changed files with 2439 additions and 741 deletions

View file

@ -31,5 +31,4 @@ $app = new Application([], $encryptionSystemReady);
if ($encryptionSystemReady) {
$app->registerEncryptionModule();
$app->registerHooks();
$app->registerSettings();
}

View file

@ -19,7 +19,7 @@
<user>user-encryption</user>
<admin>admin-encryption</admin>
</documentation>
<version>1.7.0</version>
<version>1.7.1</version>
<types>
<filesystem/>
</types>
@ -29,6 +29,7 @@
</dependencies>
<settings>
<admin>OCA\Encryption\Settings\Admin</admin>
<personal>OCA\Encryption\Settings\Personal</personal>
</settings>
<commands>
<command>OCA\Encryption\Command\EnableMasterKey</command>

View file

@ -266,9 +266,4 @@ class Application extends \OCP\AppFramework\App {
);
}
public function registerSettings() {
// Register settings scripts
App::registerPersonal('encryption', 'settings/settings-personal');
}
}

View file

@ -0,0 +1,95 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OCA\Encryption\Settings;
use OCA\Encryption\Session;
use OCA\Encryption\Util;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IUserSession;
use OCP\Settings\ISettings;
class Personal implements ISettings {
/** @var IConfig */
private $config;
/** @var Session */
private $session;
/** @var Util */
private $util;
/** @var IUserSession */
private $userSession;
public function __construct(IConfig $config, Session $session, Util $util, IUserSession $userSession) {
$this->config = $config;
$this->session = $session;
$this->util = $util;
$this->userSession = $userSession;
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$recoveryAdminEnabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled');
$privateKeySet = $this->session->isPrivateKeySet();
if (!$recoveryAdminEnabled && $privateKeySet) {
return new TemplateResponse('settings', 'settings/empty', [], '');
}
$userId = $this->userSession->getUser()->getUID();
$recoveryEnabledForUser = $this->util->isRecoveryEnabledForUser($userId);
$parameters = [
'recoveryEnabled' => $recoveryAdminEnabled,
'recoveryEnabledForUser' => $recoveryEnabledForUser,
'privateKeySet' => $privateKeySet,
'initialized' => $this->session->getStatus(),
];
return new TemplateResponse('encryption', 'settings-personal', $parameters, '');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
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.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return 80;
}
}

View file

@ -1,76 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Björn Schießle <bjoern@schiessle.org>
* @author Clark Tomlinson <fallen013@gmail.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
$session = new \OCA\Encryption\Session(\OC::$server->getSession());
$userSession = \OC::$server->getUserSession();
$template = new OCP\Template('encryption', 'settings-personal');
$crypt = new \OCA\Encryption\Crypto\Crypt(
\OC::$server->getLogger(),
$userSession,
\OC::$server->getConfig(),
\OC::$server->getL10N('encryption'));
$util = new \OCA\Encryption\Util(
new \OC\Files\View(),
$crypt,
\OC::$server->getLogger(),
$userSession,
\OC::$server->getConfig(),
\OC::$server->getUserManager());
$keyManager = new \OCA\Encryption\KeyManager(
\OC::$server->getEncryptionKeyStorage(),
$crypt,
\OC::$server->getConfig(),
$userSession,
$session,
\OC::$server->getLogger(), $util);
$user = $userSession->getUser()->getUID();
$view = new \OC\Files\View('/');
$privateKeySet = $session->isPrivateKeySet();
// did we tried to initialize the keys for this session?
$initialized = $session->getStatus();
$recoveryAdminEnabled = \OC::$server->getConfig()->getAppValue('encryption', 'recoveryAdminEnabled');
$recoveryEnabledForUser = $util->isRecoveryEnabledForUser($user);
$result = false;
if ($recoveryAdminEnabled || !$privateKeySet) {
$template->assign('recoveryEnabled', $recoveryAdminEnabled);
$template->assign('recoveryEnabledForUser', $recoveryEnabledForUser);
$template->assign('privateKeySet', $privateKeySet);
$template->assign('initialized', $initialized);
$result = $template->fetchPage();
}
return $result;

View file

@ -26,8 +26,6 @@ use OCA\FederatedFileSharing\Notifier;
$app = new \OCA\FederatedFileSharing\AppInfo\Application();
$eventDispatcher = \OC::$server->getEventDispatcher();
$app->registerSettings();
$manager = \OC::$server->getNotificationManager();
$manager->registerNotifier(function() {
return \OC::$server->query(Notifier::class);

View file

@ -6,7 +6,7 @@
<licence>AGPL</licence>
<author>Bjoern Schiessle</author>
<author>Roeland Jago Douma</author>
<version>1.3.0</version>
<version>1.3.1</version>
<namespace>FederatedFileSharing</namespace>
<category>other</category>
<dependencies>
@ -14,5 +14,7 @@
</dependencies>
<settings>
<admin>OCA\FederatedFileSharing\Settings\Admin</admin>
<personal>OCA\FederatedFileSharing\Settings\Personal</personal>
<personal-section>OCA\FederatedFileSharing\Settings\PersonalSection</personal-section>
</settings>
</info>

View file

@ -69,13 +69,6 @@ class Application extends App {
});
}
/**
* register personal and admin settings page
*/
public function registerSettings() {
\OCP\App::registerPersonal('federatedfilesharing', 'settings-personal');
}
/**
* get instance of federated share provider
*

View file

@ -0,0 +1,101 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OCA\FederatedFileSharing\Settings;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Settings\ISettings;
class Personal implements ISettings {
/** @var FederatedShareProvider */
private $federatedShareProvider;
/** @var IUserSession */
private $userSession;
/** @var IL10N */
private $l;
/** @var IURLGenerator */
private $urlGenerator;
/** @var \OC_Defaults */
private $defaults;
public function __construct(
FederatedShareProvider $federatedShareProvider, #
IUserSession $userSession,
IL10N $l,
IURLGenerator $urlGenerator,
\OC_Defaults $defaults
) {
$this->federatedShareProvider = $federatedShareProvider;
$this->userSession = $userSession;
$this->l = $l;
$this->urlGenerator = $urlGenerator;
$this->defaults = $defaults;
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$cloudID = $this->userSession->getUser()->getCloudId();
$url = 'https://nextcloud.com/federation#' . $cloudID;
$parameters = [
'outgoingServer2serverShareEnabled' => $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(),
'message_with_URL' => $this->l->t('Share with me through my #Nextcloud Federated Cloud ID, see %s', [$url]),
'message_without_URL' => $this->l->t('Share with me through my #Nextcloud Federated Cloud ID', [$cloudID]),
'logoPath' => $this->urlGenerator->imagePath('core', 'logo-icon.svg'),
'reference' => $url,
'cloudId' => $cloudID,
'color' => $this->defaults->getColorPrimary(),
'textColor' => "#ffffff",
];
return new TemplateResponse('federatedfilesharing', 'settings-personal', $parameters, '');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
return 'sharing';
}
/**
* @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
* @since 9.1
*/
public function getPriority() {
return 40;
}
}

View file

@ -0,0 +1,86 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OCA\FederatedFileSharing\Settings;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Settings\IIconSection;
class PersonalSection implements IIconSection {
/** @var IURLGenerator */
private $urlGenerator;
/** @var IL10N */
private $l;
public function __construct(IURLGenerator $urlGenerator, IL10N $l) {
$this->urlGenerator = $urlGenerator;
$this->l = $l;
}
/**
* returns the relative path to an 16*16 icon describing the section.
* e.g. '/core/img/places/files.svg'
*
* @returns string
* @since 13.0.0
*/
public function getIcon() {
return $this->urlGenerator->imagePath('core', 'actions/share.svg');
}
/**
* returns the ID of the section. It is supposed to be a lower case string,
* e.g. 'ldap'
*
* @returns string
* @since 9.1
*/
public function getID() {
return 'sharing';
}
/**
* returns the translated name as it should be displayed, e.g. 'LDAP / AD
* integration'. Use the L10N service to translate it.
*
* @return string
* @since 9.1
*/
public function getName() {
return $this->l->t('Sharing');
}
/**
* @return int whether the form should be rather on the top or bottom of
* the settings navigation. The sections are arranged in ascending order of
* the priority values. It is required to return a value between 0 and 99.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return 15;
}
}

View file

@ -1,72 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bjoern Schiessle <bjoern@schiessle.org>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Jan-Christoph Borchardt <hey@jancborchardt.net>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
use OCA\FederatedFileSharing\AppInfo\Application;
\OC_Util::checkLoggedIn();
$l = \OC::$server->getL10N('federatedfilesharing');
$app = new Application();
$federatedShareProvider = $app->getFederatedShareProvider();
$isIE8 = false;
preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches);
if (count($matches) > 0 && $matches[1] <= 9) {
$isIE8 = true;
}
$cloudID = \OC::$server->getUserSession()->getUser()->getCloudId();
$url = 'https://nextcloud.com/federation#' . $cloudID;
$logoPath = \OC::$server->getURLGenerator()->imagePath('core', 'logo-icon.svg');
/** @var \OCP\Defaults $theme */
$theme = \OC::$server->query(\OCP\Defaults::class);
$color = $theme->getColorPrimary();
$textColor = "#ffffff";
if(\OC::$server->getAppManager()->isEnabledForUser("theming")) {
$logoPath = $theme->getLogo();
try {
$util = \OC::$server->query("\OCA\Theming\Util");
if($util->invertTextColor($color)) {
$textColor = "#000000";
}
} catch (OCP\AppFramework\QueryException $e) {
}
}
$tmpl = new OCP\Template('federatedfilesharing', 'settings-personal');
$tmpl->assign('outgoingServer2serverShareEnabled', $federatedShareProvider->isOutgoingServer2serverShareEnabled());
$tmpl->assign('message_with_URL', $l->t('Share with me through my #Nextcloud Federated Cloud ID, see %s', [$url]));
$tmpl->assign('message_without_URL', $l->t('Share with me through my #Nextcloud Federated Cloud ID', [$cloudID]));
$tmpl->assign('logoPath', $logoPath);
$tmpl->assign('reference', $url);
$tmpl->assign('cloudId', $cloudID);
$tmpl->assign('showShareIT', !$isIE8);
$tmpl->assign('color', $color);
$tmpl->assign('textColor', $textColor);
return $tmpl->fetchPage();

View file

@ -18,7 +18,6 @@ style('federatedfilesharing', 'settings-personal');
<br>
<?php if ($_['showShareIT']) {?>
<p>
<?php p($l->t('Share it so your friends can share files with you:')); ?><br>
<button class="social-facebook pop-up"
@ -58,7 +57,6 @@ style('federatedfilesharing', 'settings-personal');
<?php p($l->t('Share with me via Nextcloud')); ?></a></xmp>
</p>
</div>
<?php } ?>
</div>
<?php endif; ?>

View file

@ -35,8 +35,6 @@ require_once __DIR__ . '/../3rdparty/autoload.php';
\OC_Mount_Config::$app = new \OCA\Files_External\AppInfo\Application();
$appContainer = \OC_Mount_Config::$app->getContainer();
\OC_Mount_Config::$app->registerSettings();
\OCA\Files\App::getNavigationManager()->add(function () {
$l = \OC::$server->getL10N('files_external');
return [

View file

@ -14,7 +14,7 @@ External storage can be configured using the GUI or at the command line. This se
<documentation>
<admin>admin-external-storage</admin>
</documentation>
<version>1.4.0</version>
<version>1.4.1</version>
<types>
<filesystem/>
</types>
@ -29,6 +29,8 @@ External storage can be configured using the GUI or at the command line. This se
<settings>
<admin>OCA\Files_External\Settings\Admin</admin>
<admin-section>OCA\Files_External\Settings\Section</admin-section>
<personal>OCA\Files_External\Settings\Personal</personal>
<personal-section>OCA\Files_External\Settings\PersonalSection</personal-section>
</settings>
<commands>

View file

@ -64,24 +64,6 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide
);
}
/**
* Register settings templates
*/
public function registerSettings() {
$container = $this->getContainer();
$userSession = $container->getServer()->getUserSession();
if (!$userSession->isLoggedIn()) {
return;
}
$backendService = $container->query('OCA\\Files_External\\Service\\BackendService');
/** @var \OCA\Files_External\Service\UserGlobalStoragesService $userGlobalStoragesService */
$userGlobalStoragesService = $container->query('OCA\Files_External\Service\UserGlobalStoragesService');
if (count($userGlobalStoragesService->getStorages()) > 0 || $backendService->isUserMountingAllowed()) {
\OCP\App::registerPersonal('files_external', 'personal');
}
}
/**
* @{inheritdoc}
*/

View file

@ -0,0 +1,103 @@
<?php
/**
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.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/>.
*
*/
namespace OCA\Files_External\Settings;
use OCA\Files_External\Lib\Auth\Password\GlobalAuth;
use OCA\Files_External\Service\BackendService;
use OCA\Files_External\Service\GlobalStoragesService;
use OCA\Files_External\Service\UserGlobalStoragesService;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Encryption\IManager;
use OCP\IUserSession;
use OCP\Settings\ISettings;
class Personal implements ISettings {
/** @var IManager */
private $encryptionManager;
/** @var UserGlobalStoragesService */
private $userGlobalStoragesService;
/** @var BackendService */
private $backendService;
/** @var GlobalAuth */
private $globalAuth;
/** @var IUserSession */
private $userSession;
public function __construct(
IManager $encryptionManager,
UserGlobalStoragesService $userGlobalStoragesService,
BackendService $backendService,
GlobalAuth $globalAuth,
IUserSession $userSession
) {
$this->encryptionManager = $encryptionManager;
$this->userGlobalStoragesService = $userGlobalStoragesService;
$this->backendService = $backendService;
$this->globalAuth = $globalAuth;
$this->userSession = $userSession;
}
/**
* @return TemplateResponse
*/
public function getForm() {
$uid = $this->userSession->getUser()->getUID();
$parameters = [
'encryptionEnabled' => $this->encryptionManager->isEnabled(),
'visibilityType' => BackendService::VISIBILITY_PERSONAL,
'storages' => $this->userGlobalStoragesService->getStorages(),
'backends' => $this->backendService->getAvailableBackends(),
'authMechanisms' => $this->backendService->getAuthMechanisms(),
'dependencies' => \OC_Mount_Config::dependencyMessage($this->backendService->getBackends()),
'allowUserMounting' => $this->backendService->isUserMountingAllowed(),
'globalCredentials' => $this->globalAuth->getAuth($uid),
'globalCredentialsUid' => $uid,
];
return new TemplateResponse('files_external', 'settings', $parameters, '');
}
/**
* @return string the section ID, e.g. 'sharing'
*/
public function getSection() {
return 'externalstorages';
}
/**
* @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 40;
}
}

View file

@ -0,0 +1,67 @@
<?php
/**
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.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/>.
*
*/
namespace OCA\Files_External\Settings;
use OCA\Files_External\Service\BackendService;
use OCA\Files_External\Service\UserGlobalStoragesService;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserSession;
class PersonalSection extends Section {
/** @var IUserSession */
private $userSession;
/** @var UserGlobalStoragesService */
private $userGlobalStoragesService;
/** @var BackendService */
private $backendService;
public function __construct(
IURLGenerator $url,
IL10N $l,
IUserSession $userSession,
UserGlobalStoragesService $userGlobalStoragesService,
BackendService $backendService
) {
parent::__construct($url, $l);
$this->userSession = $userSession;
$this->userGlobalStoragesService = $userGlobalStoragesService;
$this->backendService = $backendService;
}
public function getID() {
if (!$this->userSession->isLoggedIn()) {
// we need to return the proper id while installing/upgrading the app
return parent::getID();
}
if (count($this->userGlobalStoragesService->getStorages()) > 0 || $this->backendService->isUserMountingAllowed()) {
return parent::getID();
} else {
// by returning a different id, no matching settings will be found and the item will be hidden
return null;
}
}
}

View file

@ -1,47 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Joas Schilling <coding@schilljs.com>
* @author Michael Gapczynski <GapczynskiM@gmail.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Vincent Petry <pvince81@owncloud.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
use \OCA\Files_External\Service\BackendService;
// we must use the same container
$appContainer = \OC_Mount_Config::$app->getContainer();
$backendService = $appContainer->query('OCA\Files_External\Service\BackendService');
$userStoragesService = $appContainer->query('OCA\Files_External\Service\UserStoragesService');
$globalAuth = $appContainer->query('OCA\Files_External\Lib\Auth\Password\GlobalAuth');
$tmpl = new OCP\Template('files_external', 'settings');
$tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled());
$tmpl->assign('visibilityType', BackendService::VISIBILITY_PERSONAL);
$tmpl->assign('storages', $userStoragesService->getStorages());
$tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends()));
$tmpl->assign('backends', $backendService->getAvailableBackends());
$tmpl->assign('authMechanisms', $backendService->getAuthMechanisms());
$uid = \OC::$server->getUserSession()->getUser()->getUID();
$tmpl->assign('globalCredentials', $globalAuth->getAuth($uid));
$tmpl->assign('globalCredentialsUid', $uid);
$tmpl->assign('allowUserMounting', $backendService->isUserMountingAllowed());
return $tmpl->fetchPage();

View file

@ -28,4 +28,8 @@
<step>OCA\TwoFactorBackupCodes\Migration\CopyEntriesFromOldTable</step>
</post-migration>
</repair-steps>
<settings>
<personal>OCA\TwoFactorBackupCodes\Settings\Personal</personal>
</settings>
</info>

View file

@ -37,7 +37,6 @@ class Application extends App {
*/
public function register() {
$this->registerHooksAndEvents();
$this->registerPersonalPage();
}
/**
@ -52,11 +51,4 @@ class Application extends App {
$mapper = $this->getContainer()->query(BackupCodeMapper::class);
$mapper->deleteCodesByUserId($params['uid']);
}
/**
* Register personal settings for notifications and emails
*/
public function registerPersonalPage() {
\OCP\App::registerPersonal($this->getContainer()->getAppName(), 'settings/personal');
}
}

View file

@ -0,0 +1,82 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OCA\TwoFactorBackupCodes\Settings;
use OCA\TwoFactorBackupCodes\AppInfo\Application;
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IUserSession;
use OCP\Settings\ISettings;
class Personal implements ISettings {
/** @var Application */
private $app;
/** @var BackupCodesProvider */
private $provider;
/** @var IUserSession */
private $userSession;
public function __construct(Application $app, BackupCodesProvider $provider, IUserSession $userSession) {
$this->app = $app;
$this->provider = $provider;
$this->userSession = $userSession;
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$templateOwner = 'settings';
$templateName = 'settings/empty';
if ($this->provider->isActive($this->userSession->getUser())) {
$templateOwner = $this->app->getContainer()->getAppName();
$templateName = 'personal';
}
return new TemplateResponse($templateOwner, $templateName, [], '');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
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.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return 40;
}
}

View file

@ -1,19 +0,0 @@
<?php
use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Template;
// @codeCoverageIgnoreStart
/* @var $provider BackupCodesProvider */
$provider = OC::$server->query(BackupCodesProvider::class);
$user = OC::$server->getUserSession()->getUser();
if ($provider->isActive($user)) {
$tmpl = new Template('twofactor_backupcodes', 'personal');
return $tmpl->fetchPage();
} else {
return "";
}
// @codeCoverageIgnoreEnd

View file

@ -2135,6 +2135,127 @@
</declaration>
</table>
<table>
<!-- Extra personal settings sections -->
<name>*dbprefix*personal_sections</name>
<declaration>
<field>
<name>id</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>64</length>
</field>
<field>
<name>class</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<field>
<name>priority</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>1</length>
</field>
<index>
<name>personal_sections_id_index</name>
<primary>true</primary>
<field>
<name>id</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>personal_sections_class</name>
<unique>true</unique>
<field>
<name>class</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration>
</table>
<table>
<!-- Extra personal settings -->
<name>*dbprefix*personal_settings</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<length>4</length>
</field>
<field>
<name>class</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>255</length>
</field>
<!-- id of the section, foreign key: admin_sections.id -->
<field>
<name>section</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>64</length>
</field>
<field>
<name>priority</name>
<type>integer</type>
<default></default>
<notnull>true</notnull>
<length>1</length>
</field>
<index>
<name>personal_settings_id_index</name>
<primary>true</primary>
<field>
<name>id</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>personal_settings_class</name>
<unique>true</unique>
<field>
<name>class</name>
<sorting>ascending</sorting>
</field>
</index>
<index>
<name>personal_settings_section</name>
<unique>false</unique>
<field>
<name>section</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration>
</table>
<table>
<name>*dbprefix*accounts</name>

View file

@ -806,10 +806,12 @@ return array(
'OC\\Settings\\Controller\\CertificateController' => $baseDir . '/settings/Controller/CertificateController.php',
'OC\\Settings\\Controller\\ChangePasswordController' => $baseDir . '/settings/Controller/ChangePasswordController.php',
'OC\\Settings\\Controller\\CheckSetupController' => $baseDir . '/settings/Controller/CheckSetupController.php',
'OC\\Settings\\Controller\\CommonSettingsTrait' => $baseDir . '/settings/Controller/CommonSettingsTrait.php',
'OC\\Settings\\Controller\\EncryptionController' => $baseDir . '/settings/Controller/EncryptionController.php',
'OC\\Settings\\Controller\\GroupsController' => $baseDir . '/settings/Controller/GroupsController.php',
'OC\\Settings\\Controller\\LogSettingsController' => $baseDir . '/settings/Controller/LogSettingsController.php',
'OC\\Settings\\Controller\\MailSettingsController' => $baseDir . '/settings/Controller/MailSettingsController.php',
'OC\\Settings\\Controller\\PersonalSettingsController' => $baseDir . '/settings/Controller/PersonalSettingsController.php',
'OC\\Settings\\Controller\\SecuritySettingsController' => $baseDir . '/settings/Controller/SecuritySettingsController.php',
'OC\\Settings\\Controller\\UsersController' => $baseDir . '/settings/Controller/UsersController.php',
'OC\\Settings\\Hooks' => $baseDir . '/settings/Hooks.php',
@ -817,6 +819,10 @@ return array(
'OC\\Settings\\Manager' => $baseDir . '/lib/private/Settings/Manager.php',
'OC\\Settings\\Mapper' => $baseDir . '/lib/private/Settings/Mapper.php',
'OC\\Settings\\Middleware\\SubadminMiddleware' => $baseDir . '/settings/Middleware/SubadminMiddleware.php',
'OC\\Settings\\Personal\\Additional' => $baseDir . '/lib/private/Settings/Personal/Additional.php',
'OC\\Settings\\Personal\\PersonalInfo' => $baseDir . '/lib/private/Settings/Personal/PersonalInfo.php',
'OC\\Settings\\Personal\\Security' => $baseDir . '/lib/private/Settings/Personal/Security.php',
'OC\\Settings\\Personal\\SyncClients' => $baseDir . '/lib/private/Settings/Personal/SyncClients.php',
'OC\\Settings\\RemoveOrphaned' => $baseDir . '/lib/private/Settings/RemoveOrphaned.php',
'OC\\Settings\\Section' => $baseDir . '/lib/private/Settings/Section.php',
'OC\\Setup' => $baseDir . '/lib/private/Setup.php',

View file

@ -836,10 +836,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Settings\\Controller\\CertificateController' => __DIR__ . '/../../..' . '/settings/Controller/CertificateController.php',
'OC\\Settings\\Controller\\ChangePasswordController' => __DIR__ . '/../../..' . '/settings/Controller/ChangePasswordController.php',
'OC\\Settings\\Controller\\CheckSetupController' => __DIR__ . '/../../..' . '/settings/Controller/CheckSetupController.php',
'OC\\Settings\\Controller\\CommonSettingsTrait' => __DIR__ . '/../../..' . '/settings/Controller/CommonSettingsTrait.php',
'OC\\Settings\\Controller\\EncryptionController' => __DIR__ . '/../../..' . '/settings/Controller/EncryptionController.php',
'OC\\Settings\\Controller\\GroupsController' => __DIR__ . '/../../..' . '/settings/Controller/GroupsController.php',
'OC\\Settings\\Controller\\LogSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/LogSettingsController.php',
'OC\\Settings\\Controller\\MailSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/MailSettingsController.php',
'OC\\Settings\\Controller\\PersonalSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/PersonalSettingsController.php',
'OC\\Settings\\Controller\\SecuritySettingsController' => __DIR__ . '/../../..' . '/settings/Controller/SecuritySettingsController.php',
'OC\\Settings\\Controller\\UsersController' => __DIR__ . '/../../..' . '/settings/Controller/UsersController.php',
'OC\\Settings\\Hooks' => __DIR__ . '/../../..' . '/settings/Hooks.php',
@ -847,6 +849,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Settings\\Manager' => __DIR__ . '/../../..' . '/lib/private/Settings/Manager.php',
'OC\\Settings\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Settings/Mapper.php',
'OC\\Settings\\Middleware\\SubadminMiddleware' => __DIR__ . '/../../..' . '/settings/Middleware/SubadminMiddleware.php',
'OC\\Settings\\Personal\\Additional' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/Additional.php',
'OC\\Settings\\Personal\\PersonalInfo' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/PersonalInfo.php',
'OC\\Settings\\Personal\\Security' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/Security.php',
'OC\\Settings\\Personal\\SyncClients' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/SyncClients.php',
'OC\\Settings\\RemoveOrphaned' => __DIR__ . '/../../..' . '/lib/private/Settings/RemoveOrphaned.php',
'OC\\Settings\\Section' => __DIR__ . '/../../..' . '/lib/private/Settings/Section.php',
'OC\\Setup' => __DIR__ . '/../../..' . '/lib/private/Setup.php',

View file

@ -177,14 +177,14 @@ class NavigationManager implements INavigationManager {
]);
}
// Personal settings
// Personal and (if applicable) admin settings
$this->add([
'type' => 'settings',
'id' => 'personal',
'id' => 'settings',
'order' => 1,
'href' => $this->urlGenerator->linkToRoute('settings_personal'),
'name' => $l->t('Personal'),
'icon' => $this->urlGenerator->imagePath('settings', 'personal.svg'),
'href' => $this->urlGenerator->linkToRoute('settings.PersonalSettings.index'),
'name' => $l->t('Settings'),
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
]);
// Logout
@ -211,18 +211,6 @@ class NavigationManager implements INavigationManager {
'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
]);
}
if ($this->isAdmin()) {
// Admin settings
$this->add([
'type' => 'settings',
'id' => 'admin',
'order' => 2,
'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index'),
'name' => $l->t('Admin'),
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
]);
}
}
if ($this->appManager === 'null') {

View file

@ -42,6 +42,7 @@
namespace OC;
use bantu\IniGetWrapper\IniGetWrapper;
use OC\Accounts\AccountManager;
use OC\App\AppManager;
use OC\App\AppStore\Bundles\BundleFetcher;
use OC\App\AppStore\Fetcher\AppFetcher;
@ -970,7 +971,12 @@ class Server extends ServerContainer implements IServerContainer {
$c->getLockingProvider(),
$c->getRequest(),
new \OC\Settings\Mapper($c->getDatabaseConnection()),
$c->getURLGenerator()
$c->getURLGenerator(),
$c->query(AccountManager::class),
$c->getGroupManager(),
$c->getL10NFactory(),
$c->getThemingDefaults(),
$c->getAppManager()
);
return $manager;
});

View file

@ -61,7 +61,7 @@ class Additional implements ISettings {
$parameters['mail_smtppassword'] = '********';
}
return new TemplateResponse('settings', 'admin/additional-mail', $parameters, '');
return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
}
/**

View file

@ -68,7 +68,7 @@ class Encryption implements ISettings {
'encryptionModules' => $encryptionModuleList,
];
return new TemplateResponse('settings', 'admin/encryption', $parameters, '');
return new TemplateResponse('settings', 'settings/admin/encryption', $parameters, '');
}
/**

View file

@ -137,7 +137,7 @@ class Server implements ISettings {
'cli_based_cron_user' => function_exists('posix_getpwuid') ? posix_getpwuid(fileowner(\OC::$configDir . 'config.php'))['name'] : '',
];
return new TemplateResponse('settings', 'admin/server', $parameters, '');
return new TemplateResponse('settings', 'settings/admin/server', $parameters, '');
}
/**

View file

@ -30,7 +30,7 @@ class ServerDevNotice implements ISettings {
* @return TemplateResponse
*/
public function getForm() {
return new TemplateResponse('settings', 'admin/server.development.notice');
return new TemplateResponse('settings', 'settings/admin/server.development.notice');
}
/**

View file

@ -67,7 +67,7 @@ class Sharing implements ISettings {
'enableLinkPasswordByDefault' => $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no'),
];
return new TemplateResponse('settings', 'admin/sharing', $parameters, '');
return new TemplateResponse('settings', 'settings/admin/sharing', $parameters, '');
}
/**

View file

@ -48,7 +48,7 @@ class TipsTricks implements ISettings {
'databaseOverload' => $databaseOverload,
];
return new TemplateResponse('settings', 'admin/tipstricks', $parameters, '');
return new TemplateResponse('settings', 'settings/admin/tipstricks', $parameters, '');
}
/**

View file

@ -23,24 +23,25 @@
namespace OC\Settings;
use OC\Accounts\AccountManager;
use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
use OCP\Encryption\IManager as EncryptionManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Lock\ILockingProvider;
use OCP\Settings\ISettings;
use OCP\Settings\IManager;
use OCP\Settings\ISection;
class Manager implements IManager {
const TABLE_ADMIN_SETTINGS = 'admin_settings';
const TABLE_ADMIN_SECTIONS = 'admin_sections';
/** @var ILogger */
private $log;
/** @var IDBConnection */
@ -61,6 +62,16 @@ class Manager implements IManager {
private $request;
/** @var IURLGenerator */
private $url;
/** @var AccountManager */
private $accountManager;
/** @var IGroupManager */
private $groupManager;
/** @var IFactory */
private $l10nFactory;
/** @var \OC_Defaults */
private $defaults;
/** @var IAppManager */
private $appManager;
/**
* @param ILogger $log
@ -73,6 +84,10 @@ class Manager implements IManager {
* @param IRequest $request
* @param Mapper $mapper
* @param IURLGenerator $url
* @param AccountManager $accountManager
* @param IGroupManager $groupManager
* @param IFactory $l10nFactory
* @param \OC_Defaults $defaults
*/
public function __construct(
ILogger $log,
@ -84,7 +99,12 @@ class Manager implements IManager {
ILockingProvider $lockingProvider,
IRequest $request,
Mapper $mapper,
IURLGenerator $url
IURLGenerator $url,
AccountManager $accountManager,
IGroupManager $groupManager,
IFactory $l10nFactory,
\OC_Defaults $defaults,
IAppManager $appManager
) {
$this->log = $log;
$this->dbc = $dbc;
@ -96,6 +116,11 @@ class Manager implements IManager {
$this->lockingProvider = $lockingProvider;
$this->request = $request;
$this->url = $url;
$this->accountManager = $accountManager;
$this->groupManager = $groupManager;
$this->l10nFactory = $l10nFactory;
$this->defaults = $defaults;
$this->appManager = $appManager;
}
/**
@ -103,10 +128,17 @@ class Manager implements IManager {
*/
public function setupSettings(array $settings) {
if (isset($settings[IManager::KEY_ADMIN_SECTION])) {
$this->setupAdminSection($settings[IManager::KEY_ADMIN_SECTION]);
$this->setupSectionEntry($settings[IManager::KEY_ADMIN_SECTION], 'admin');
}
if (isset($settings[IManager::KEY_ADMIN_SETTINGS])) {
$this->setupAdminSettings($settings[IManager::KEY_ADMIN_SETTINGS]);
$this->setupSettingsEntry($settings[IManager::KEY_ADMIN_SETTINGS], 'admin');
}
if (isset($settings[IManager::KEY_PERSONAL_SECTION])) {
$this->setupSectionEntry($settings[IManager::KEY_PERSONAL_SECTION], 'personal');
}
if (isset($settings[IManager::KEY_PERSONAL_SETTINGS])) {
$this->setupSettingsEntry($settings[IManager::KEY_PERSONAL_SETTINGS], 'personal');
}
}
@ -122,15 +154,22 @@ class Manager implements IManager {
$appInfo = \OC_App::getAppInfo($appId); // hello static legacy
if (isset($appInfo['settings'][IManager::KEY_ADMIN_SECTION])) {
$this->mapper->remove(self::TABLE_ADMIN_SECTIONS, trim($appInfo['settings'][IManager::KEY_ADMIN_SECTION], '\\'));
$this->mapper->remove(Mapper::TABLE_ADMIN_SECTIONS, trim($appInfo['settings'][IManager::KEY_ADMIN_SECTION], '\\'));
}
if (isset($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS])) {
$this->mapper->remove(self::TABLE_ADMIN_SETTINGS, trim($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS], '\\'));
$this->mapper->remove(Mapper::TABLE_ADMIN_SETTINGS, trim($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS], '\\'));
}
if (isset($appInfo['settings'][IManager::KEY_PERSONAL_SECTION])) {
$this->mapper->remove(Mapper::TABLE_PERSONAL_SECTIONS, trim($appInfo['settings'][IManager::KEY_PERSONAL_SECTION], '\\'));
}
if (isset($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS])) {
$this->mapper->remove(Mapper::TABLE_PERSONAL_SETTINGS, trim($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS], '\\'));
}
}
public function checkForOrphanedClassNames() {
$tables = [self::TABLE_ADMIN_SECTIONS, self::TABLE_ADMIN_SETTINGS];
$tables = [Mapper::TABLE_ADMIN_SECTIONS, Mapper::TABLE_ADMIN_SETTINGS, Mapper::TABLE_PERSONAL_SECTIONS, Mapper::TABLE_PERSONAL_SETTINGS];
foreach ($tables as $table) {
$classes = $this->mapper->getClasses($table);
foreach ($classes as $className) {
@ -145,10 +184,11 @@ class Manager implements IManager {
/**
* @param string $sectionClassName
* @param string $type either 'admin' or 'personal'
*/
private function setupAdminSection($sectionClassName) {
private function setupSectionEntry($sectionClassName, $type) {
if (!class_exists($sectionClassName)) {
$this->log->debug('Could not find admin section class ' . $sectionClassName);
$this->log->debug('Could not find ' . ucfirst($type) . ' section class ' . $sectionClassName);
return;
}
try {
@ -160,37 +200,38 @@ class Manager implements IManager {
if (!$section instanceof ISection) {
$this->log->error(
'Admin section instance must implement \OCP\ISection. Invalid class: {class}',
ucfirst($type) .' section instance must implement \OCP\ISection. Invalid class: {class}',
['class' => $sectionClassName]
);
return;
}
if (!$this->hasAdminSection(get_class($section))) {
$this->addAdminSection($section);
$table = $this->getSectionTableForType($type);
if(!$this->hasSection(get_class($section), $table)) {
$this->addSection($section, $table);
} else {
$this->updateAdminSection($section);
$this->updateSection($section, $table);
}
}
private function addAdminSection(ISection $section) {
$this->mapper->add(self::TABLE_ADMIN_SECTIONS, [
private function addSection(ISection $section, $table) {
$this->mapper->add($table, [
'id' => $section->getID(),
'class' => get_class($section),
'priority' => $section->getPriority(),
]);
}
private function addAdminSettings(ISettings $settings) {
$this->mapper->add(self::TABLE_ADMIN_SETTINGS, [
private function addSettings(ISettings $settings, $table) {
$this->mapper->add($table, [
'class' => get_class($settings),
'section' => $settings->getSection(),
'priority' => $settings->getPriority(),
]);
}
private function updateAdminSettings(ISettings $settings) {
private function updateSettings(ISettings $settings, $table) {
$this->mapper->update(
self::TABLE_ADMIN_SETTINGS,
$table,
'class',
get_class($settings),
[
@ -200,9 +241,9 @@ class Manager implements IManager {
);
}
private function updateAdminSection(ISection $section) {
private function updateSection(ISection $section, $table) {
$this->mapper->update(
self::TABLE_ADMIN_SECTIONS,
$table,
'class',
get_class($section),
[
@ -214,23 +255,24 @@ class Manager implements IManager {
/**
* @param string $className
* @param string $table
* @return bool
*/
private function hasAdminSection($className) {
return $this->mapper->has(self::TABLE_ADMIN_SECTIONS, $className);
private function hasSection($className, $table) {
return $this->mapper->has($table, $className);
}
/**
* @param string $className
* @return bool
*/
private function hasAdminSettings($className) {
return $this->mapper->has(self::TABLE_ADMIN_SETTINGS, $className);
private function hasSettings($className, $table) {
return $this->mapper->has($table, $className);
}
private function setupAdminSettings($settingsClassName) {
private function setupSettingsEntry($settingsClassName, $type) {
if (!class_exists($settingsClassName)) {
$this->log->debug('Could not find admin section class ' . $settingsClassName);
$this->log->debug('Could not find ' . $type . ' section class ' . $settingsClassName);
return;
}
@ -244,18 +286,37 @@ class Manager implements IManager {
if (!$settings instanceof ISettings) {
$this->log->error(
'Admin section instance must implement \OCP\Settings\ISection. Invalid class: {class}',
ucfirst($type) . ' section instance must implement \OCP\Settings\ISettings. Invalid class: {class}',
['class' => $settingsClassName]
);
return;
}
if (!$this->hasAdminSettings(get_class($settings))) {
$this->addAdminSettings($settings);
$table = $this->getSettingsTableForType($type);
if (!$this->hasSettings(get_class($settings), $table)) {
$this->addSettings($settings, $table);
} else {
$this->updateAdminSettings($settings);
$this->updateSettings($settings, $table);
}
}
private function getSectionTableForType($type) {
if($type === 'admin') {
return Mapper::TABLE_ADMIN_SECTIONS;
} else if($type === 'personal') {
return Mapper::TABLE_PERSONAL_SECTIONS;
}
throw new \InvalidArgumentException('"admin" or "personal" expected');
}
private function getSettingsTableForType($type) {
if($type === 'admin') {
return Mapper::TABLE_ADMIN_SETTINGS;
} else if($type === 'personal') {
return Mapper::TABLE_PERSONAL_SETTINGS;
}
throw new \InvalidArgumentException('"admin" or "personal" expected');
}
private function query($className) {
try {
return \OC::$server->query($className);
@ -337,6 +398,47 @@ class Manager implements IManager {
return $forms;
}
/**
* @param string $section
* @return ISection[]
*/
private function getBuiltInPersonalSettings($section) {
$forms = [];
try {
if ($section === 'personal-info') {
/** @var ISettings $form */
$form = new Personal\PersonalInfo(
$this->config,
$this->userManager,
$this->groupManager,
$this->accountManager,
$this->appManager,
$this->l10nFactory,
$this->l
);
$forms[$form->getPriority()] = [$form];
}
if($section === 'security') {
/** @var ISettings $form */
$form = new Personal\Security();
$forms[$form->getPriority()] = [$form];
}
if($section === 'sync-clients') {
/** @var ISettings $form */
$form = new Personal\SyncClients($this->config, $this->defaults);
$forms[$form->getPriority()] = [$form];
}
if ($section === 'additional') {
/** @var ISettings $form */
$form = new Personal\Additional($this->config);
$forms[$form->getPriority()] = [$form];
}
} catch (QueryException $e) {
// skip
}
return $forms;
}
/**
* @inheritdoc
*/
@ -358,4 +460,72 @@ class Manager implements IManager {
ksort($settings);
return $settings;
}
/**
* @inheritdoc
*/
public function getPersonalSections() {
$sections = [
0 => [new Section('personal-info', $this->l->t('Personal info'), 0, $this->url->imagePath('core', 'actions/info.svg'))],
5 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('settings', 'password.svg'))],
15 => [new Section('sync-clients', $this->l->t('Sync clients'), 0, $this->url->imagePath('settings', 'change.svg'))],
];
$legacyForms = \OC_App::getForms('personal');
if(count($legacyForms) > 0 && $this->hasLegacyPersonalSettingsToRender($legacyForms)) {
$sections[98] = [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))];
}
$rows = $this->mapper->getPersonalSectionsFromDB();
foreach ($rows as $row) {
if (!isset($sections[$row['priority']])) {
$sections[$row['priority']] = [];
}
try {
$sections[$row['priority']][] = $this->query($row['class']);
} catch (QueryException $e) {
// skip
}
}
ksort($sections);
return $sections;
}
/**
* @param $forms
* @return bool
*/
private function hasLegacyPersonalSettingsToRender($forms) {
foreach ($forms as $form) {
if(trim($form) !== '') {
return true;
}
}
return false;
}
/**
* @inheritdoc
*/
public function getPersonalSettings($section) {
$settings = $this->getBuiltInPersonalSettings($section);
$dbRows = $this->mapper->getPersonalSettingsFromDB($section);
foreach ($dbRows as $row) {
if (!isset($settings[$row['priority']])) {
$settings[$row['priority']] = [];
}
try {
$settings[$row['priority']][] = $this->query($row['class']);
} catch (QueryException $e) {
// skip
}
}
ksort($settings);
return $settings;
}
}

View file

@ -28,6 +28,8 @@ use OCP\IDBConnection;
class Mapper {
const TABLE_ADMIN_SETTINGS = 'admin_settings';
const TABLE_ADMIN_SECTIONS = 'admin_sections';
const TABLE_PERSONAL_SETTINGS = 'personal_settings';
const TABLE_PERSONAL_SECTIONS = 'personal_sections';
/** @var IDBConnection */
private $dbc;
@ -46,9 +48,30 @@ class Mapper {
* @return array[] [['class' => string, 'priority' => int], ...]
*/
public function getAdminSettingsFromDB($section) {
return $this->getSettingsFromDB(self::TABLE_ADMIN_SETTINGS, $section);
}
/**
* Get the configured personal settings from the database for the provided section
*
* @param string $section
* @return array[] [['class' => string, 'priority' => int], ...]
*/
public function getPersonalSettingsFromDB($section) {
return $this->getSettingsFromDB(self::TABLE_PERSONAL_SETTINGS, $section);
}
/**
* Get the configured settings from the database for the provided table and section
*
* @param $table
* @param $section
* @return array
*/
private function getSettingsFromDB($table, $section) {
$query = $this->dbc->getQueryBuilder();
$query->select(['class', 'priority'])
->from(self::TABLE_ADMIN_SETTINGS)
->from($table)
->where($query->expr()->eq('section', $this->dbc->getQueryBuilder()->createParameter('section')))
->setParameter('section', $section);
@ -62,11 +85,39 @@ class Mapper {
* @return array[] [['class' => string, 'priority' => int], ...]
*/
public function getAdminSectionsFromDB() {
return $this->getSectionsFromDB('admin');
}
/**
* Get the configured admin sections from the database
*
* @return array[] [['class' => string, 'priority' => int], ...]
*/
public function getPersonalSectionsFromDB() {
return $this->getSectionsFromDB('personal');
}
/**
* Get the configured sections from the database by table
*
* @param string $type either 'personal' or 'admin'
* @return array[] [['class' => string, 'priority' => int], ...]
*/
public function getSectionsFromDB($type) {
if($type === 'admin') {
$sectionsTable = self::TABLE_ADMIN_SECTIONS;
$settingsTable = self::TABLE_ADMIN_SETTINGS;
} else if($type === 'personal') {
$sectionsTable = self::TABLE_PERSONAL_SECTIONS;
$settingsTable = self::TABLE_PERSONAL_SETTINGS;
} else {
throw new \InvalidArgumentException('"admin" or "personal" expected');
}
$query = $this->dbc->getQueryBuilder();
$query->selectDistinct('s.class')
->addSelect('s.priority')
->from(self::TABLE_ADMIN_SECTIONS, 's')
->from(self::TABLE_ADMIN_SETTINGS, 'f')
->from($sectionsTable, 's')
->from($settingsTable, 'f')
->where($query->expr()->eq('s.id', 'f.section'));
$result = $query->execute();
return array_map(function ($row) {
@ -76,7 +127,7 @@ class Mapper {
}
/**
* @param string $table Mapper::TABLE_ADMIN_SECTIONS or Mapper::TABLE_ADMIN_SETTINGS
* @param string $table one of the Mapper::TABLE_* constants
* @param array $values
*/
public function add($table, array $values) {
@ -91,7 +142,7 @@ class Mapper {
/**
* returns the registered classes in the given table
*
* @param $table Mapper::TABLE_ADMIN_SECTIONS or Mapper::TABLE_ADMIN_SETTINGS
* @param string $table one of the Mapper::TABLE_* constants
* @return string[]
*/
public function getClasses($table) {
@ -110,7 +161,7 @@ class Mapper {
/**
* Check if a class is configured in the database
*
* @param string $table Mapper::TABLE_ADMIN_SECTIONS or Mapper::TABLE_ADMIN_SETTINGS
* @param string $table one of the Mapper::TABLE_* constants
* @param string $className
* @return bool
*/
@ -131,8 +182,8 @@ class Mapper {
/**
* deletes an settings or admin entry from the given table
*
* @param $table Mapper::TABLE_ADMIN_SECTIONS or Mapper::TABLE_ADMIN_SETTINGS
* @param $className
* @param string $table one of the Mapper::TABLE_* constants
* @param string $className
*/
public function remove($table, $className) {
$query = $this->dbc->getQueryBuilder();
@ -143,10 +194,10 @@ class Mapper {
}
/**
* @param $table Mapper::TABLE_ADMIN_SECTIONS or Mapper::TABLE_ADMIN_SETTINGS
* @param $idCol
* @param $id
* @param $values
* @param string $table one of the Mapper::TABLE_* constants
* @param string $idCol
* @param string $id
* @param array $values
*/
public function update($table, $idCol, $id, $values) {
$query = $this->dbc->getQueryBuilder();

View file

@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Personal;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Settings\ISettings;
class Additional implements ISettings {
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
return new TemplateResponse('settings', 'settings/empty');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
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.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return '5';
}
}

View file

@ -0,0 +1,284 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Personal;
use OC\Accounts\AccountManager;
use OCA\FederatedFileSharing\AppInfo\Application;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Files\FileInfo;
use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Settings\ISettings;
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;
const COMMON_LANGUAGE_CODES = [
'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
];
/** @var IL10N */
private $l;
/**
* @param IConfig $config
* @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param AccountManager $accountManager
* @param IFactory $l10nFactory
* @param IL10N $l
*/
public function __construct(
IConfig $config,
IUserManager $userManager,
IGroupManager $groupManager,
AccountManager $accountManager,
IAppManager $appManager,
IFactory $l10nFactory,
IL10N $l
) {
$this->config = $config;
$this->userManager = $userManager;
$this->accountManager = $accountManager;
$this->groupManager = $groupManager;
$this->appManager = $appManager;
$this->l10nFactory = $l10nFactory;
$this->l = $l;
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$federatedFileSharingEnabled = $this->appManager->isEnabledForUser('federatedfilesharing');
$lookupServerUploadEnabled = false;
if($federatedFileSharingEnabled) {
$federatedFileSharing = new Application();
$shareProvider = $federatedFileSharing->getFederatedShareProvider();
$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
}
$uid = \OC_User::getUser();
$user = $this->userManager->get($uid);
$userData = $this->accountManager->getUser($user);
$storageInfo = \OC_Helper::getStorageInfo('/');
if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
$totalSpace = $this->l->t('Unlimited');
} else {
$totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
}
$languageParameters = $this->getLanguages($user);
$messageParameters = $this->getMessageParameters($userData);
$parameters = [
'total_space' => $totalSpace,
'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
'usage_relative' => $storageInfo['relative'],
'quota' => $storageInfo['quota'],
'avatarChangeSupported' => \OC_User::canUserChangeAvatar($uid),
'lookupServerUploadEnabled' => $lookupServerUploadEnabled,
'avatarScope' => $userData[AccountManager::PROPERTY_AVATAR]['scope'],
'displayNameChangeSupported' => \OC_User::canUserChangeDisplayName($uid),
'displayName' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['value'],
'displayNameScope' => $userData[AccountManager::PROPERTY_DISPLAYNAME]['scope'],
'email' => $userData[AccountManager::PROPERTY_EMAIL]['value'],
'emailScope' => $userData[AccountManager::PROPERTY_EMAIL]['scope'],
'emailVerification' => $userData[AccountManager::PROPERTY_EMAIL]['verified'],
'phone' => $userData[AccountManager::PROPERTY_PHONE]['value'],
'phoneScope' => $userData[AccountManager::PROPERTY_PHONE]['scope'],
'address' => $userData[AccountManager::PROPERTY_ADDRESS]['value'],
'addressScope' => $userData[AccountManager::PROPERTY_ADDRESS]['scope'],
'website' => $userData[AccountManager::PROPERTY_WEBSITE]['value'],
'websiteScope' => $userData[AccountManager::PROPERTY_WEBSITE]['scope'],
'websiteVerification' => $userData[AccountManager::PROPERTY_WEBSITE]['verified'],
'twitter' => $userData[AccountManager::PROPERTY_TWITTER]['value'],
'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
'groups' => $this->getGroups($user),
'passwordChangeSupported' => \OC_User::canUserChangePassword($uid),
] + $messageParameters + $languageParameters;
return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
return 'personal-info';
}
/**
* @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
* @since 9.1
*/
public function getPriority() {
return 10;
}
/**
* returns a sorted list of the user's group GIDs
*
* @param IUser $user
* @return array
*/
private function getGroups(IUser $user) {
$groups = array_map(
function(IGroup $group) {
return $group->getGID();
},
$this->groupManager->getUserGroups($user)
);
sort($groups);
return $groups;
}
/**
* returns the user language, common language and other languages in an
* associative array
*
* @param IUser $user
* @return array
*/
private function getLanguages(IUser $user) {
$forceLanguage = $this->config->getSystemValue('force_language', false);
if($forceLanguage !== false) {
return [];
}
$uid = $user->getUID();
$userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
$languageCodes = $this->l10nFactory->findAvailableLanguages();
$commonLanguages = [];
$languages = [];
foreach($languageCodes as $lang) {
$l = \OC::$server->getL10N('settings', $lang);
// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
$potentialName = (string) $l->t('__language_name__');
if($l->getLanguageCode() === $lang && substr($potentialName, 0, 1) !== '_') {//first check if the language name is in the translation file
$ln = array('code' => $lang, 'name' => $potentialName);
} elseif ($lang === 'en') {
$ln = ['code' => $lang, 'name' => 'English (US)'];
}else{//fallback to language code
$ln=array('code'=>$lang, 'name'=>$lang);
}
// put appropriate languages into appropriate arrays, to print them sorted
// used language -> common languages -> divider -> other languages
if ($lang === $userLang) {
$userLang = $ln;
} elseif (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
$commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)]=$ln;
} else {
$languages[]=$ln;
}
}
// if user language is not available but set somehow: show the actual code as name
if (!is_array($userLang)) {
$userLang = [
'code' => $userLang,
'name' => $userLang,
];
}
ksort($commonLanguages);
// sort now by displayed language not the iso-code
usort( $languages, function ($a, $b) {
if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
// If a doesn't have a name, but b does, list b before a
return 1;
}
if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
// If a does have a name, but b doesn't, list a before b
return -1;
}
// Otherwise compare the names
return strcmp($a['name'], $b['name']);
});
return [
'activelanguage' => $userLang,
'commonlanguages' => $commonLanguages,
'languages' => $languages
];
}
/**
* @param array $userData
* @return array
*/
private function getMessageParameters(array $userData) {
$needVerifyMessage = [AccountManager::PROPERTY_EMAIL, AccountManager::PROPERTY_WEBSITE, AccountManager::PROPERTY_TWITTER];
$messageParameters = [];
foreach ($needVerifyMessage as $property) {
switch ($userData[$property]['verified']) {
case AccountManager::VERIFIED:
$message = $this->l->t('Verifying');
break;
case AccountManager::VERIFICATION_IN_PROGRESS:
$message = $this->l->t('Verifying …');
break;
default:
$message = $this->l->t('Verify');
}
$messageParameters[$property . 'Message'] = $message;
}
return $messageParameters;
}
}

View file

@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Personal;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Settings\ISettings;
class Security implements ISettings {
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
return new TemplateResponse('settings', 'settings/personal/security');
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
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.
*
* E.g.: 70
* @since 9.1
*/
public function getPriority() {
return 10;
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Personal;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\Settings\ISettings;
class SyncClients implements ISettings {
/** @var IConfig */
private $config;
/** @var \OC_Defaults */
private $defaults;
public function __construct(IConfig $config, \OC_Defaults $defaults) {
$this->config = $config;
$this->defaults = $defaults;
}
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
$parameters = [ 'clients' => $this->getClientLinks() ];
return new TemplateResponse('settings', 'settings/personal/sync-clients', $parameters);
}
/**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
public function getSection() {
return 'sync-clients';
}
/**
* @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
* @since 9.1
*/
public function getPriority() {
return 20;
}
/**
* returns an array containing links to the various clients
*
* @return array
*/
private function getClientLinks() {
$clients = [
'desktop' => $this->config->getSystemValue('customclient_desktop', $this->defaults->getSyncClientUrl()),
'android' => $this->config->getSystemValue('customclient_android', $this->defaults->getAndroidClientUrl()),
'ios' => $this->config->getSystemValue('customclient_ios', $this->defaults->getiOSClientUrl())
];
return $clients;
}
}

View file

@ -37,6 +37,16 @@ interface IManager {
*/
const KEY_ADMIN_SECTION = 'admin-section';
/**
* @since 13.0.0
*/
const KEY_PERSONAL_SETTINGS = 'personal';
/**
* @since 13.0.0
*/
const KEY_PERSONAL_SECTION = 'personal-section';
/**
* sets up settings according to data specified by an apps info.xml, within
* the <settings> element.
@ -87,6 +97,14 @@ interface IManager {
*/
public function getAdminSections();
/**
* returns a list of the personal sections
*
* @return array array of ISection[] where key is the priority
* @since 13.0.0
*/
public function getPersonalSections();
/**
* returns a list of the admin settings
*
@ -95,4 +113,13 @@ interface IManager {
* @since 9.1.0
*/
public function getAdminSettings($section);
/**
* returns a list of the personal settings
*
* @param string $section the section id for which to load the settings
* @return array array of IPersonal[] where key is the priority
* @since 13.0.0
*/
public function getPersonalSettings($section);
}

View file

@ -28,19 +28,17 @@ use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\INavigationManager;
use OCP\IRequest;
use OCP\Settings\IIconSection;
use OCP\Settings\IManager as ISettingsManager;
use OCP\Settings\ISection;
use OCP\Template;
/**
* @package OC\Settings\Controller
*/
class AdminSettingsController extends Controller {
use CommonSettingsTrait;
/** @var INavigationManager */
private $navigationManager;
/** @var ISettingsManager */
private $settingsManager;
/**
* @param string $appName
@ -67,32 +65,20 @@ class AdminSettingsController extends Controller {
*/
public function index($section) {
$this->navigationManager->setActiveEntry('admin');
$templateParams = [];
$templateParams = array_merge($templateParams, $this->getNavigationParameters($section));
$templateParams = array_merge($templateParams, $this->getSettings($section));
return new TemplateResponse('settings', 'admin/frame', $templateParams);
return $this->getIndexResponse('admin', $section);
}
/**
* @param string $section
* @return array
*/
private function getSettings($section) {
$html = '';
protected function getSettings($section) {
$settings = $this->settingsManager->getAdminSettings($section);
foreach ($settings as $prioritizedSettings) {
foreach ($prioritizedSettings as $setting) {
/** @var \OCP\Settings\ISettings $setting */
$form = $setting->getForm();
$html .= $form->renderAs('')->render();
}
}
$formatted = $this->formatSettings($settings);
if($section === 'additional') {
$html .= $this->getLegacyForms();
$formatted['content'] .= $this->getLegacyForms();
}
return ['content' => $html];
return $formatted;
}
/**
@ -119,42 +105,11 @@ class AdminSettingsController extends Controller {
);
}, $forms);
$out = new Template('settings', 'admin/additional');
$out = new Template('settings', 'settings/additional');
$out->assign('forms', $forms);
return $out->fetchPage();
}
/**
* @param string $currentSection
* @return array
*/
private function getNavigationParameters($currentSection) {
$sections = $this->settingsManager->getAdminSections();
$templateParameters = [];
/** @var \OC\Settings\Section[] $prioritizedSections */
foreach($sections as $prioritizedSections) {
foreach ($prioritizedSections as $section) {
if (empty($this->settingsManager->getAdminSettings($section->getID()))) {
continue;
}
$icon = '';
if ($section instanceof IIconSection) {
$icon = $section->getIcon();
}
$templateParameters[] = [
'anchor' => $section->getID(),
'section-name' => $section->getName(),
'active' => $section->getID() === $currentSection,
'icon' => $icon,
];
}
}
return [
'forms' => $templateParameters
];
}
}

View file

@ -0,0 +1,126 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Settings\IManager as ISettingsManager;
use OCP\Settings\IIconSection;
use OCP\Settings\ISettings;
trait CommonSettingsTrait {
/** @var ISettingsManager */
private $settingsManager;
/**
* @param string $currentSection
* @return array
*/
private function getNavigationParameters($currentType, $currentSection) {
$templateParameters = [
'personal' => $this->formatPersonalSections($currentType, $currentSection),
'admin' => []
];
if(\OC_User::isAdminUser(\OC_User::getUser())) {
$templateParameters['admin'] = $this->formatAdminSections($currentType, $currentSection);
}
return [
'forms' => $templateParameters
];
}
protected function formatSections($sections, $currentSection, $type, $currentType) {
$templateParameters = [];
/** @var \OCP\Settings\ISection[] $prioritizedSections */
foreach($sections as $prioritizedSections) {
foreach ($prioritizedSections as $section) {
if($type === 'admin') {
$settings = $this->settingsManager->getAdminSettings($section->getID());
} else if($type === 'personal') {
$settings = $this->settingsManager->getPersonalSettings($section->getID());
}
if (empty($settings)) {
continue;
}
$icon = '';
if ($section instanceof IIconSection) {
$icon = $section->getIcon();
}
$active = $section->getID() === $currentSection
&& $type === $currentType;
$templateParameters[] = [
'anchor' => $section->getID(),
'section-name' => $section->getName(),
'active' => $active,
'icon' => $icon,
];
}
}
return $templateParameters;
}
protected function formatPersonalSections($currentType, $currentSections) {
$sections = $this->settingsManager->getPersonalSections();
$templateParameters = $this->formatSections($sections, $currentSections, 'personal', $currentType);
return $templateParameters;
}
protected function formatAdminSections($currentType, $currentSections) {
$sections = $this->settingsManager->getAdminSections();
$templateParameters = $this->formatSections($sections, $currentSections, 'admin', $currentType);
return $templateParameters;
}
/**
* @param ISettings[] $settings
* @return array
*/
private function formatSettings($settings) {
$html = '';
foreach ($settings as $prioritizedSettings) {
foreach ($prioritizedSettings as $setting) {
/** @var \OCP\Settings\ISettings $setting */
$form = $setting->getForm();
$html .= $form->renderAs('')->render();
}
}
return ['content' => $html];
}
private function getIndexResponse($type, $section) {
$templateParams = [];
$templateParams = array_merge($templateParams, $this->getNavigationParameters($type, $section));
$templateParams = array_merge($templateParams, $this->getSettings($section));
return new TemplateResponse('settings', 'settings/frame', $templateParams);
}
abstract protected function getSettings($section);
}

View file

@ -0,0 +1,106 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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 OC\Settings\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\INavigationManager;
use OCP\IRequest;
use OCP\Settings\IManager as ISettingsManager;
use OCP\Template;
class PersonalSettingsController extends Controller {
use CommonSettingsTrait;
/** @var INavigationManager */
private $navigationManager;
public function __construct(
$appName,
IRequest $request,
INavigationManager $navigationManager,
ISettingsManager $settingsManager
) {
parent::__construct($appName, $request);
$this->navigationManager = $navigationManager;
$this->settingsManager = $settingsManager;
}
/**
* @param string $section
* @return TemplateResponse
*
* @NoCSRFRequired
* @NoAdminRequired
* @NoSubadminRequired
*/
public function index($section) {
$this->navigationManager->setActiveEntry('personal');
return $this->getIndexResponse('personal', $section);
}
/**
* @param string $section
* @return array
*/
protected function getSettings($section) {
$settings = $this->settingsManager->getPersonalSettings($section);
$formatted = $this->formatSettings($settings);
if($section === 'additional') {
$formatted['content'] .= $this->getLegacyForms();
}
return $formatted;
}
/**
* @return bool|string
*/
private function getLegacyForms() {
$forms = \OC_App::getForms('personal');
$forms = array_map(function ($form) {
if (preg_match('%(<h2(?P<class>[^>]*)>.*?</h2>)%i', $form, $regs)) {
$sectionName = str_replace('<h2' . $regs['class'] . '>', '', $regs[0]);
$sectionName = str_replace('</h2>', '', $sectionName);
$anchor = strtolower($sectionName);
$anchor = str_replace(' ', '-', $anchor);
return array(
'anchor' => $anchor,
'section-name' => $sectionName,
'form' => $form
);
}
return array(
'form' => $form
);
}, $forms);
$out = new Template('settings', 'settings/additional');
$out->assign('forms', $forms);
return $out->fetchPage();
}
}

View file

@ -1296,3 +1296,11 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
margin-bottom: 12px;
opacity: .7;
}
.settings-caption {
font-weight: bold;
line-height: 44px;
padding: 0 12px;
white-space: nowrap;
text-overflow: ellipsis;
}

View file

@ -0,0 +1,7 @@
$(document).ready(function () {
var collection = new OC.Settings.AuthTokenCollection();
var view = new OC.Settings.AuthTokenView({
collection: collection
});
view.reload();
});

View file

@ -4,6 +4,7 @@
* Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
* 2013, Morris Jobke <morris.jobke@gmail.com>
* 2016, Christoph Wurst <christoph@owncloud.com>
* 2017, Arthur Schiwon <blizzz@arthur-schiwon.de>
* This file is licensed under the Affero General Public License version 3 or later.
* See the COPYING-README file.
*/
@ -394,51 +395,6 @@ $(document).ready(function () {
$('#removeavatar').removeClass('hidden').addClass('inlineblock');
}
});
// Show token views
var collection = new OC.Settings.AuthTokenCollection();
var view = new OC.Settings.AuthTokenView({
collection: collection
});
view.reload();
// 'redirect' to anchor sections
// anchors are lost on redirects (e.g. while solving the 2fa challenge) otherwise
// example: /settings/person?section=devices will result in /settings/person?#devices
if (!window.location.hash) {
var query = OC.parseQueryString(location.search);
if (query && query.section) {
OC.Util.History.replaceState({});
window.location.hash = query.section;
}
}
});
if (!OC.Encryption) {
OC.Encryption = {};
}
OC.Encryption.msg = {
start: function (selector, msg) {
var spinner = '<img src="' + OC.imagePath('core', 'loading-small.gif') + '">';
$(selector)
.html(msg + ' ' + spinner)
.removeClass('success')
.removeClass('error')
.stop(true, true)
.show();
},
finished: function (selector, data) {
if (data.status === "success") {
$(selector).html(data.data.message)
.addClass('success')
.stop(true, true)
.delay(3000);
} else {
$(selector).html(data.data.message).addClass('error');
}
}
};
OC.Settings.updateAvatar = updateAvatar;

View file

@ -1,281 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Christopher Schäpers <kondou@ts.unde.re>
* @author Christoph Wurst <christoph@owncloud.com>
* @author Georg Ehrke <georg@owncloud.com>
* @author Jakob Sack <mail@jakobsack.de>
* @author Jan-Christoph Borchardt <hey@jancborchardt.net>
* @author Joas Schilling <coding@schilljs.com>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Marvin Thomas Rabe <mrabe@marvinrabe.de>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vincent Petry <pvince81@owncloud.com>
* @author Volkan Gezer <volkangezer@gmail.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
OC_Util::checkLoggedIn();
$defaults = \OC::$server->getThemingDefaults();
$certificateManager = \OC::$server->getCertificateManager();
$accountManager = new \OC\Accounts\AccountManager(
\OC::$server->getDatabaseConnection(),
\OC::$server->getEventDispatcher(),
\OC::$server->getJobList()
);
$config = \OC::$server->getConfig();
$urlGenerator = \OC::$server->getURLGenerator();
// Highlight navigation entry
OC_Util::addScript('settings', 'authtoken');
OC_Util::addScript('settings', 'authtoken_collection');
OC_Util::addScript('settings', 'authtoken_view');
OC_Util::addScript('settings', 'usersettings');
OC_Util::addScript('settings', 'federationsettingsview');
OC_Util::addScript('settings', 'federationscopemenu');
OC_Util::addScript('settings', 'personal');
OC_Util::addScript('settings', 'certificates');
OC_Util::addStyle( 'settings', 'settings' );
\OC_Util::addVendorScript('strengthify/jquery.strengthify');
\OC_Util::addVendorStyle('strengthify/strengthify');
\OC_Util::addScript('files', 'jquery.fileupload');
\OC_Util::addVendorScript('jcrop/js/jquery.Jcrop');
\OC_Util::addVendorStyle('jcrop/css/jquery.Jcrop');
\OC::$server->getEventDispatcher()->dispatch('OC\Settings\Personal::loadAdditionalScripts');
// Highlight navigation entry
OC::$server->getNavigationManager()->setActiveEntry('personal');
$storageInfo=OC_Helper::getStorageInfo('/');
$user = OC::$server->getUserManager()->get(OC_User::getUser());
$forceLanguage = $config->getSystemValue('force_language', false);
if ($forceLanguage === false) {
$userLang=$config->getUserValue( OC_User::getUser(), 'core', 'lang', \OC::$server->getL10NFactory()->findLanguage() );
$languageCodes = \OC::$server->getL10NFactory()->findAvailableLanguages();
// array of common languages
$commonLangCodes = array(
'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it', 'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
);
$languages=array();
$commonLanguages = array();
foreach($languageCodes as $lang) {
$l = \OC::$server->getL10N('settings', $lang);
// TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
$potentialName = (string) $l->t('__language_name__');
if($l->getLanguageCode() === $lang && substr($potentialName, 0, 1) !== '_') {//first check if the language name is in the translation file
$ln = array('code' => $lang, 'name' => $potentialName);
} elseif ($lang === 'en') {
$ln = ['code' => $lang, 'name' => 'English (US)'];
}else{//fallback to language code
$ln=array('code'=>$lang, 'name'=>$lang);
}
// put appropriate languages into appropriate arrays, to print them sorted
// used language -> common languages -> divider -> other languages
if ($lang === $userLang) {
$userLang = $ln;
} elseif (in_array($lang, $commonLangCodes)) {
$commonLanguages[array_search($lang, $commonLangCodes)]=$ln;
} else {
$languages[]=$ln;
}
}
// if user language is not available but set somehow: show the actual code as name
if (!is_array($userLang)) {
$userLang = [
'code' => $userLang,
'name' => $userLang,
];
}
ksort($commonLanguages);
// sort now by displayed language not the iso-code
usort( $languages, function ($a, $b) {
if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
// If a doesn't have a name, but b does, list b before a
return 1;
}
if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
// If a does have a name, but b doesn't, list a before b
return -1;
}
// Otherwise compare the names
return strcmp($a['name'], $b['name']);
});
}
//links to clients
$clients = array(
'desktop' => $config->getSystemValue('customclient_desktop', $defaults->getSyncClientUrl()),
'android' => $config->getSystemValue('customclient_android', $defaults->getAndroidClientUrl()),
'ios' => $config->getSystemValue('customclient_ios', $defaults->getiOSClientUrl())
);
// only show root certificate import if external storages are enabled
$enableCertImport = false;
$externalStorageEnabled = \OC::$server->getAppManager()->isEnabledForUser('files_external');
if ($externalStorageEnabled) {
/** @var \OCA\Files_External\Service\BackendService $backendService */
$backendService = \OC_Mount_Config::$app->getContainer()->query('\OCA\Files_External\Service\BackendService');
$enableCertImport = $backendService->isUserMountingAllowed();
}
// Return template
$l = \OC::$server->getL10N('settings');
$tmpl = new OC_Template( 'settings', 'personal', 'user');
$tmpl->assign('usage', OC_Helper::humanFileSize($storageInfo['used']));
if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
$totalSpace = $l->t('Unlimited');
} else {
$totalSpace = OC_Helper::humanFileSize($storageInfo['total']);
}
$uid = $user->getUID();
$userData = $accountManager->getUser($user);
$tmpl->assign('total_space', $totalSpace);
$tmpl->assign('usage_relative', $storageInfo['relative']);
$tmpl->assign('quota', $storageInfo['quota']);
$tmpl->assign('clients', $clients);
$tmpl->assign('email', $userData[\OC\Accounts\AccountManager::PROPERTY_EMAIL]['value']);
if ($forceLanguage === false) {
$tmpl->assign('languages', $languages);
$tmpl->assign('commonlanguages', $commonLanguages);
$tmpl->assign('activelanguage', $userLang);
}
$tmpl->assign('passwordChangeSupported', OC_User::canUserChangePassword(OC_User::getUser()));
$tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC_User::getUser()));
$tmpl->assign('displayName', $userData[\OC\Accounts\AccountManager::PROPERTY_DISPLAYNAME]['value']);
$tmpl->assign('phone', $userData[\OC\Accounts\AccountManager::PROPERTY_PHONE]['value']);
$tmpl->assign('website', $userData[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['value']);
$tmpl->assign('twitter', $userData[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['value']);
$tmpl->assign('address', $userData[\OC\Accounts\AccountManager::PROPERTY_ADDRESS]['value']);
$tmpl->assign('avatarScope', $userData[\OC\Accounts\AccountManager::PROPERTY_AVATAR]['scope']);
$tmpl->assign('displayNameScope', $userData[\OC\Accounts\AccountManager::PROPERTY_DISPLAYNAME]['scope']);
$tmpl->assign('phoneScope', $userData[\OC\Accounts\AccountManager::PROPERTY_PHONE]['scope']);
$tmpl->assign('emailScope', $userData[\OC\Accounts\AccountManager::PROPERTY_EMAIL]['scope']);
$tmpl->assign('websiteScope', $userData[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['scope']);
$tmpl->assign('twitterScope', $userData[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['scope']);
$tmpl->assign('addressScope', $userData[\OC\Accounts\AccountManager::PROPERTY_ADDRESS]['scope']);
$tmpl->assign('websiteVerification', $userData[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['verified']);
$tmpl->assign('twitterVerification', $userData[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['verified']);
$tmpl->assign('emailVerification', $userData[\OC\Accounts\AccountManager::PROPERTY_EMAIL]['verified']);
$needVerifyMessage = [\OC\Accounts\AccountManager::PROPERTY_EMAIL, \OC\Accounts\AccountManager::PROPERTY_WEBSITE, \OC\Accounts\AccountManager::PROPERTY_TWITTER];
foreach ($needVerifyMessage as $property) {
switch ($userData[$property]['verified']) {
case \OC\Accounts\AccountManager::VERIFIED:
$message = $l->t('Verifying');
break;
case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
$message = $l->t('Verifying …');
break;
default:
$message = $l->t('Verify');
}
$tmpl->assign($property . 'Message', $message);
}
$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
$tmpl->assign('certs', $certificateManager->listCertificates());
$tmpl->assign('showCertificates', $enableCertImport);
$tmpl->assign('urlGenerator', $urlGenerator);
$federatedFileSharingEnabled = \OC::$server->getAppManager()->isEnabledForUser('federatedfilesharing');
$lookupServerUploadEnabled = false;
if ($federatedFileSharingEnabled) {
$federatedFileSharing = new \OCA\FederatedFileSharing\AppInfo\Application();
$shareProvider = $federatedFileSharing->getFederatedShareProvider();
$lookupServerUploadEnabled = $shareProvider->isLookupServerUploadEnabled();
}
$tmpl->assign('lookupServerUploadEnabled', $lookupServerUploadEnabled);
// Get array of group ids for this user
$groups = \OC::$server->getGroupManager()->getUserIdGroups(OC_User::getUser());
$groups2 = array_map(function($group) { return $group->getGID(); }, $groups);
sort($groups2);
$tmpl->assign('groups', $groups2);
// add hardcoded forms from the template
$formsAndMore = [];
$formsAndMore[]= ['anchor' => 'personal-settings', 'section-name' => $l->t('Personal info')];
$formsAndMore[]= ['anchor' => 'security', 'section-name' => $l->t('Security')];
$formsAndMore[]= ['anchor' => 'clientsbox', 'section-name' => $l->t('Sync clients')];
$forms=OC_App::getForms('personal');
// add bottom hardcoded forms from the template
if ($enableCertImport) {
$certificatesTemplate = new OC_Template('settings', 'certificates');
$certificatesTemplate->assign('type', 'personal');
$certificatesTemplate->assign('uploadRoute', 'settings.Certificate.addPersonalRootCertificate');
$certificatesTemplate->assign('certs', $certificateManager->listCertificates());
$certificatesTemplate->assign('urlGenerator', $urlGenerator);
$forms[] = $certificatesTemplate->fetchPage();
}
$formsMap = array_map(function($form){
if (preg_match('%(<h2(?P<class>[^>]*)>.*?</h2>)%i', $form, $regs)) {
$sectionName = str_replace('<h2'.$regs['class'].'>', '', $regs[0]);
$sectionName = str_replace('</h2>', '', $sectionName);
if (strpos($regs['class'], 'data-anchor-name') !== false) {
preg_match('%.*data-anchor-name="(?P<anchor>[^"]*)"%i', $regs['class'], $matches);
$anchor = $matches['anchor'];
} else {
$anchor = strtolower($sectionName);
$anchor = str_replace(' ', '-', $anchor);
}
return array(
'anchor' => $anchor,
'section-name' => $sectionName,
'form' => $form
);
}
return array(
'form' => $form
);
}, $forms);
$formsAndMore = array_merge($formsAndMore, $formsMap);
$tmpl->assign('forms', $formsAndMore);
$tmpl->printPage();

View file

@ -65,6 +65,7 @@ $application->registerRoutes($this, [
['name' => 'Certificate#removePersonalRootCertificate', 'url' => '/settings/personal/certificate/{certificateIdentifier}', 'verb' => 'DELETE'],
['name' => 'Certificate#addSystemRootCertificate', 'url' => '/settings/admin/certificate', 'verb' => 'POST'],
['name' => 'Certificate#removeSystemRootCertificate', 'url' => '/settings/admin/certificate/{certificateIdentifier}', 'verb' => 'DELETE'],
['name' => 'PersonalSettings#index', 'url' => '/settings/user/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'personal-info']],
['name' => 'AdminSettings#index', 'url' => '/settings/admin/{section}', 'verb' => 'GET', 'defaults' => ['section' => 'server']],
['name' => 'AdminSettings#form', 'url' => '/settings/admin/{section}', 'verb' => 'GET'],
['name' => 'ChangePassword#changePersonalPassword', 'url' => '/settings/personal/changepassword', 'verb' => 'POST'],
@ -82,8 +83,6 @@ $application->registerRoutes($this, [
// Settings pages
$this->create('settings_help', '/settings/help')
->actionInclude('settings/help.php');
$this->create('settings_personal', '/settings/personal')
->actionInclude('settings/personal.php');
$this->create('settings_users', '/settings/users')
->actionInclude('settings/users.php');
// Settings ajax actions

View file

@ -0,0 +1,25 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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/>.
*
*/
# used for Personal/Additional settings as fallback for legacy settings
?>

View file

@ -30,9 +30,39 @@ script('files', 'jquery.fileupload');
<div id="app-navigation">
<ul>
<li class="settings-caption">Personal</li>
<?php
foreach($_['forms'] as $form) {
foreach($_['forms']['personal'] as $form) {
if (isset($form['anchor'])) {
$anchor = \OC::$server->getURLGenerator()->linkToRoute('settings.PersonalSettings.index', ['section' => $form['anchor']]);
$class = 'nav-icon-' . $form['anchor'];
$sectionName = $form['section-name'];
$active = $form['active'] ? ' class="active"' : '';
?>
<li <?php print_unescaped($form['active'] ? ' class="active"' : ''); ?>>
<a href="<?php p($anchor); ?>">
<?php if (!empty($form['icon'])) { ?>
<img alt="" src="<?php print_unescaped($form['icon']); ?>">
<span><?php p($form['section-name']); ?></span>
<?php } else { ?>
<span class="no-icon"><?php p($form['section-name']); ?></span>
<?php } ?>
</a>
</li>
<?php
}
}
?>
<?php
if(!empty($_['forms']['admin'])) {
?>
<li class="settings-caption">Administration</li>
<?php
}
foreach($_['forms']['admin'] as $form) {
if (isset($form['anchor'])) {
$anchor = \OC::$server->getURLGenerator()->linkToRoute('settings.AdminSettings.index', ['section' => $form['anchor']]);
$class = 'nav-icon-' . $form['anchor'];
$sectionName = $form['section-name'];

View file

@ -0,0 +1,316 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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/>.
*
*/
/** @var \OCP\IL10N $l */
/** @var array $_ */
script('settings', [
'usersettings',
'federationsettingsview',
'federationscopemenu',
'settings/personalInfo',
]);
vendor_script('strengthify/jquery.strengthify');
vendor_style('strengthify/strengthify');
vendor_script('jcrop/js/jquery.Jcrop');
vendor_style('jcrop/css/jquery.Jcrop');
?>
<div id="quota" class="section">
<div style="width:<?php p($_['usage_relative']);?>%"
<?php if($_['usage_relative'] > 80): ?> class="quota-warning" <?php endif; ?>>
<p id="quotatext">
<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
<?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong>',
[$_['usage'], $_['total_space']]));?>
<?php else: ?>
<?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)',
[$_['usage'], $_['total_space'], $_['usage_relative']]));?>
<?php endif ?>
</p>
</div>
</div>
<div id="personal-settings">
<div id="personal-settings-avatar-container">
<form id="avatarform" class="section" method="post" action="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.postAvatar')); ?>">
<h2>
<label><?php p($l->t('Profile picture')); ?></label>
<span class="icon-password"/>
</h2>
<div id="displayavatar">
<div class="avatardiv"></div>
<div class="warning hidden"></div>
<?php if ($_['avatarChangeSupported']): ?>
<label for="uploadavatar" class="inlineblock button icon-upload svg" id="uploadavatarbutton" title="<?php p($l->t('Upload new')); ?>"></label>
<div class="inlineblock button icon-folder svg" id="selectavatar" title="<?php p($l->t('Select from Files')); ?>"></div>
<div class="hidden button icon-delete svg" id="removeavatar" title="<?php p($l->t('Remove image')); ?>"></div>
<input type="file" name="files[]" id="uploadavatar" class="hiddenuploadfield">
<p><em><?php p($l->t('png or jpg, max. 20 MB')); ?></em></p>
<?php else: ?>
<?php p($l->t('Picture provided by original account')); ?>
<?php endif; ?>
</div>
<div id="cropper" class="hidden">
<div class="inner-container">
<div class="inlineblock button" id="abortcropperbutton"><?php p($l->t('Cancel')); ?></div>
<div class="inlineblock button primary" id="sendcropperbutton"><?php p($l->t('Choose as profile picture')); ?></div>
</div>
</div>
<span class="icon-checkmark hidden"/>
<?php if($_['lookupServerUploadEnabled']) { ?>
<input type="hidden" id="avatarscope" value="<?php p($_['avatarScope']) ?>">
<?php } ?>
</form>
</div>
<div id="personal-settings-container">
<div class="personal-settings-setting-box">
<form id="displaynameform" class="section">
<h2>
<label for="displayname"><?php p($l->t('Full name')); ?></label>
<span class="icon-password"/>
</h2>
<input type="text" id="displayname" name="displayname"
<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
value="<?php p($_['displayName']) ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<?php if(!$_['displayNameChangeSupported']) { ?>
<span><?php if(isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span>
<?php } ?>
<span class="icon-checkmark hidden"/>
<?php if($_['lookupServerUploadEnabled']) { ?>
<input type="hidden" id="displaynamescope" value="<?php p($_['displayNameScope']) ?>">
<?php } ?>
</form>
</div>
<div class="personal-settings-setting-box">
<form id="emailform" class="section">
<h2>
<label for="email"><?php p($l->t('Email')); ?></label>
<span class="icon-password"/>
</h2>
<div class="verify <?php if ($_['email'] === '' || $_['emailScope'] !== 'public') p('hidden'); ?>">
<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
<?php
switch($_['emailVerification']) {
case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
p(image_path('core', 'actions/verifying.svg'));
break;
case \OC\Accounts\AccountManager::VERIFIED:
p(image_path('core', 'actions/verified.svg'));
break;
default:
p(image_path('core', 'actions/verify.svg'));
}
?>">
</div>
<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
placeholder="<?php p($l->t('Your email address')); ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<?php if(!$_['displayNameChangeSupported']) { ?>
<span><?php if(isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span>
<?php } ?>
<?php if($_['displayNameChangeSupported']) { ?>
<br />
<em><?php p($l->t('For password reset and notifications')); ?></em>
<?php } ?>
<span class="icon-checkmark hidden"/>
<?php if($_['lookupServerUploadEnabled']) { ?>
<input type="hidden" id="emailscope" value="<?php p($_['emailScope']) ?>">
<?php } ?>
</form>
</div>
<?php if($_['lookupServerUploadEnabled']) { ?>
<div class="personal-settings-setting-box">
<form id="phoneform" class="section">
<h2>
<label for="phone"><?php p($l->t('Phone number')); ?></label>
<span class="icon-password"/>
</h2>
<input type="tel" id="phone" name="phone"
value="<?php p($_['phone']) ?>"
placeholder="<?php p($l->t('Your phone number')); ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>">
</form>
</div>
<div class="personal-settings-setting-box">
<form id="addressform" class="section">
<h2>
<label for="address"><?php p($l->t('Address')); ?></label>
<span class="icon-password"/>
</h2>
<input type="text" id="address" name="address"
placeholder="<?php p($l->t('Your postal address')); ?>"
value="<?php p($_['address']) ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>">
</form>
</div>
<div class="personal-settings-setting-box">
<form id="websiteform" class="section">
<h2>
<label for="website"><?php p($l->t('Website')); ?></label>
<span class="icon-password"/>
</h2>
<div class="verify <?php if ($_['website'] === '' || $_['websiteScope'] !== 'public') p('hidden'); ?>">
<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
<?php
switch($_['websiteVerification']) {
case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
p(image_path('core', 'actions/verifying.svg'));
break;
case \OC\Accounts\AccountManager::VERIFIED:
p(image_path('core', 'actions/verified.svg'));
break;
default:
p(image_path('core', 'actions/verify.svg'));
}
?>"
<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
>
<div class="verification-dialog popovermenu bubble menu">
<div class="verification-dialog-content">
<p class="explainVerification"></p>
<p class="verificationCode"></p>
<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
</div>
</div>
</div>
<input type="text" name="website" id="website" value="<?php p($_['website']); ?>"
placeholder="<?php p($l->t('Link https://…')); ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>">
</form>
</div>
<div class="personal-settings-setting-box">
<form id="twitterform" class="section">
<h2>
<label for="twitter"><?php p($l->t('Twitter')); ?></label>
<span class="icon-password"/>
</h2>
<div class="verify <?php if ($_['twitter'] === '' || $_['twitterScope'] !== 'public') p('hidden'); ?>">
<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
<?php
switch($_['twitterVerification']) {
case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
p(image_path('core', 'actions/verifying.svg'));
break;
case \OC\Accounts\AccountManager::VERIFIED:
p(image_path('core', 'actions/verified.svg'));
break;
default:
p(image_path('core', 'actions/verify.svg'));
}
?>"
<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
>
<div class="verification-dialog popovermenu bubble menu">
<div class="verification-dialog-content">
<p class="explainVerification"></p>
<p class="verificationCode"></p>
<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
</div>
</div>
</div>
<input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>"
placeholder="<?php p($l->t('Twitter handle @…')); ?>"
autocomplete="on" autocapitalize="none" autocorrect="off" />
<span class="icon-checkmark hidden"/>
<input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>">
</form>
</div>
<?php } ?>
<span class="msg"></span>
</div>
</div>
<div id="groups" class="section">
<h2><?php p($l->t('Groups')); ?></h2>
<p><?php p($l->t('You are member of the following groups:')); ?></p>
<p>
<?php p(implode(', ', $_['groups'])); ?>
</p>
</div>
<?php
if($_['passwordChangeSupported']) {
script('jquery-showpassword');
?>
<form id="passwordform" class="section">
<h2 class="inlineblock"><?php p($l->t('Password'));?></h2>
<div id="password-error-msg" class="msg success inlineblock" style="display: none;">Saved</div>
<br>
<label for="pass1" class="hidden-visually"><?php p($l->t('Current password')); ?>: </label>
<input type="password" id="pass1" name="oldpassword"
placeholder="<?php p($l->t('Current password'));?>"
autocomplete="off" autocapitalize="none" autocorrect="off" />
<div class="personal-show-container">
<label for="pass2" class="hidden-visually"><?php p($l->t('New password'));?>: </label>
<input type="password" id="pass2" name="newpassword"
placeholder="<?php p($l->t('New password')); ?>"
data-typetoggle="#personal-show"
autocomplete="off" autocapitalize="none" autocorrect="off" />
<input type="checkbox" id="personal-show" name="show" /><label for="personal-show" class="personal-show-label"></label>
</div>
<input id="passwordbutton" type="submit" value="<?php p($l->t('Change password')); ?>" />
<br/>
</form>
<?php
}
?>
<?php if (isset($_['activelanguage'])) { ?>
<form id="language" class="section">
<h2>
<label for="languageinput"><?php p($l->t('Language'));?></label>
</h2>
<select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language'));?>">
<option value="<?php p($_['activelanguage']['code']);?>">
<?php p($_['activelanguage']['name']);?>
</option>
<?php foreach($_['commonlanguages'] as $language):?>
<option value="<?php p($language['code']);?>">
<?php p($language['name']);?>
</option>
<?php endforeach;?>
<optgroup label=""></optgroup>
<?php foreach($_['languages'] as $language):?>
<option value="<?php p($language['code']);?>">
<?php p($language['name']);?>
</option>
<?php endforeach;?>
</select>
<a href="https://www.transifex.com/nextcloud/nextcloud/"
target="_blank" rel="noreferrer">
<em><?php p($l->t('Help translate'));?></em>
</a>
</form>
<?php } ?>

View file

@ -0,0 +1,68 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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/>.
*
*/
script('settings', [
'authtoken',
'authtoken_collection',
'authtoken_view',
'settings/authtoken-init'
]);
?>
<div id="security" class="section">
<h2><?php p($l->t('Security'));?></h2>
<p class="settings-hint hidden-when-empty"><?php p($l->t('Web, desktop and mobile clients currently logged in to your account.'));?></p>
<table class="icon-loading">
<thead class="token-list-header">
<tr>
<th><?php p($l->t('Device'));?></th>
<th><?php p($l->t('Last activity'));?></th>
<th></th>
</tr>
</thead>
<tbody class="token-list">
</tbody>
</table>
<div id="app-password-form">
<input id="app-password-name" type="text" placeholder="<?php p($l->t('App name')); ?>">
<button id="add-app-password" class="button"><?php p($l->t('Create new app password')); ?></button>
</div>
<div id="app-password-result" class="hidden">
<span>
<?php p($l->t('Use the credentials below to configure your app or device.')); ?>
<?php p($l->t('For security reasons this password will only be shown once.')); ?>
</span>
<div class="app-password-row">
<span class="app-password-label"><?php p($l->t('Username')); ?></span>
<input id="new-app-login-name" type="text" readonly="readonly"/>
</div>
<div class="app-password-row">
<span class="app-password-label"><?php p($l->t('Password')); ?></span>
<input id="new-app-password" type="text" readonly="readonly"/>
<a class="clipboardButton icon icon-clippy" data-clipboard-target="#new-app-password"></a>
<button id="app-password-hide" class="button"><?php p($l->t('Done')); ?></button>
</div>
</div>
</div>

View file

@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @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/>.
*
*/
/** @var array $_ */
?>
<div id="clientsbox" class="section clientsbox">
<h2><?php p($l->t('Get the apps to sync your files'));?></h2>
<a href="<?php p($_['clients']['desktop']); ?>" rel="noreferrer" target="_blank">
<img src="<?php print_unescaped(image_path('core', 'desktopapp.svg')); ?>"
alt="<?php p($l->t('Desktop client'));?>" />
</a>
<a href="<?php p($_['clients']['android']); ?>" rel="noreferrer" target="_blank">
<img src="<?php print_unescaped(image_path('core', 'googleplay.png')); ?>"
alt="<?php p($l->t('Android app'));?>" />
</a>
<a href="<?php p($_['clients']['ios']); ?>" rel="noreferrer" target="_blank">
<img src="<?php print_unescaped(image_path('core', 'appstore.svg')); ?>"
alt="<?php p($l->t('iOS app'));?>" />
</a>
<p>
<?php print_unescaped(str_replace(
[
'{contributeopen}',
'{linkclose}',
],
[
'<a href="https://nextcloud.com/contribute" target="_blank" rel="noreferrer">',
'</a>',
],
$l->t('If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!'))); ?>
</p>
<?php if(OC_APP::isEnabled('firstrunwizard')) {?>
<p><a class="button" href="#" id="showWizard"><?php p($l->t('Show First Run Wizard again'));?></a></p>
<?php }?>
</div>

View file

@ -22,7 +22,6 @@
*/
namespace Tests\Settings\Controller;
use OC\Settings\Admin\TipsTricks;
use OC\Settings\Controller\AdminSettingsController;
use OCP\AppFramework\Http\TemplateResponse;
@ -31,6 +30,13 @@ use OCP\IRequest;
use OCP\Settings\IManager;
use Test\TestCase;
/**
* Class AdminSettingsControllerTest
*
* @group DB
*
* @package Tests\Settings\Controller
*/
class AdminSettingsControllerTest extends TestCase {
/** @var AdminSettingsController */
private $adminSettingsController;
@ -38,8 +44,10 @@ class AdminSettingsControllerTest extends TestCase {
private $request;
/** @var INavigationManager */
private $navigationManager;
/** @var IManager */
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
private $settingsManager;
/** @var string */
private $adminUid = 'lololo';
public function setUp() {
parent::setUp();
@ -54,6 +62,16 @@ class AdminSettingsControllerTest extends TestCase {
$this->navigationManager,
$this->settingsManager
);
$user = \OC::$server->getUserManager()->createUser($this->adminUid, 'olo');
\OC_User::setUserId($user->getUID());
\OC::$server->getGroupManager()->createGroup('admin')->addUser($user);
}
public function tearDown() {
\OC::$server->getUserManager()->get($this->adminUid)->delete();
parent::tearDown();
}
public function testIndex() {
@ -61,12 +79,17 @@ class AdminSettingsControllerTest extends TestCase {
->expects($this->once())
->method('getAdminSections')
->willReturn([]);
$this->settingsManager
->expects($this->once())
->method('getPersonalSections')
->willReturn([]);
$this->settingsManager
->expects($this->once())
->method('getAdminSettings')
->with('test')
->willReturn([5 => new TipsTricks($this->getMockBuilder('\OCP\IConfig')->getMock())]);
$expected = new TemplateResponse('settings', 'admin/frame', ['forms' => [], 'content' => '']);
$expected = new TemplateResponse('settings', 'settings/frame', ['forms' => ['personal' => [], 'admin' => []], 'content' => '']);
$this->assertEquals($expected, $this->adminSettingsController->index('test'));
}
}

View file

@ -1,11 +1,10 @@
Feature: access-levels
Scenario: regular users can not see admin-level items in the Settings menu
Scenario: regular users cannot see admin-level items in the Settings menu
Given I am logged in
When I open the Settings menu
Then I see that the Settings menu is shown
And I see that the "Personal" item in the Settings menu is shown
And I see that the "Admin" item in the Settings menu is not shown
And I see that the "Settings" item in the Settings menu is shown
And I see that the "Users" item in the Settings menu is not shown
And I see that the "Help" item in the Settings menu is shown
And I see that the "Log out" item in the Settings menu is shown
@ -14,8 +13,19 @@ Feature: access-levels
Given I am logged in as the admin
When I open the Settings menu
Then I see that the Settings menu is shown
And I see that the "Personal" item in the Settings menu is shown
And I see that the "Admin" item in the Settings menu is shown
And I see that the "Settings" item in the Settings menu is shown
And I see that the "Users" item in the Settings menu is shown
And I see that the "Help" item in the Settings menu is shown
And I see that the "Log out" item in the Settings menu is shown
Scenario: regular users cannot see admin-level items on the Settings page
Given I am logged in
When I visit the settings page
Then I see that the "Personal" settings panel is shown
And I see that the "Administration" settings panel is not shown
Scenario: admin users can see admin-level items on the Settings page
Given I am logged in as the admin
When I visit the settings page
Then I see that the "Personal" settings panel is shown
And I see that the "Administration" settings panel is shown

View file

@ -66,6 +66,15 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
describedAs($itemText . " item in Settings menu");
}
/**
* @param string $itemText
* @return Locator
*/
private static function settingsPanelFor($itemText) {
return Locator::forThe()->xpath("//div[@id = 'app-navigation']//ul//li[@class = 'settings-caption' and normalize-space() = '$itemText']")->
describedAs($itemText . " item in Settings panel");
}
/**
* @When I open the Settings menu
*/
@ -82,6 +91,14 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
$this->actor->find(self::usersMenuItem(), 2)->click();
}
/**
* @When I visit the settings page
*/
public function iVisitTheSettingsPage() {
$this->iOpenTheSettingsMenu();
$this->actor->find(self::menuItemFor('Settings'), 2)->click();
}
/**
* @When I log out
*/
@ -120,4 +137,25 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
}
}
/**
* @Then I see that the :itemText settings panel is shown
*/
public function iSeeThatTheItemSettingsPanelIsShown($itemText) {
PHPUnit_Framework_Assert::assertTrue(
$this->actor->find(self::settingsPanelFor($itemText), 10)->isVisible()
);
}
/**
* @Then I see that the :itemText settings panel is not shown
*/
public function iSeeThatTheItemSettingsPanelIsNotShown($itemText) {
try {
PHPUnit_Framework_Assert::assertFalse(
$this->actor->find(self::settingsPanelFor($itemText), 10)->isVisible()
);
} catch (NoSuchElementException $exception) {
}
}
}

View file

@ -119,7 +119,7 @@ class ElementWrapper {
/**
* Returns whether the wrapped element is visible or not.
*
* @return boolbean true if the wrapped element is visible, false otherwise.
* @return bool true if the wrapped element is visible, false otherwise.
*/
public function isVisible() {
$commandCallback = function() {

View file

@ -97,7 +97,7 @@ class AdditionalTest extends TestCase {
$expected = new TemplateResponse(
'settings',
'admin/additional-mail',
'settings/admin/additional-mail',
[
'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'),
'mail_domain' => 'mx.nextcloud.com',

View file

@ -81,7 +81,7 @@ class EncryptionTest extends TestCase {
->willReturn(['entry']);
$expected = new TemplateResponse(
'settings',
'admin/encryption',
'settings/admin/encryption',
[
'encryptionEnabled' => $enabled,
'encryptionReady' => $enabled,
@ -116,7 +116,7 @@ class EncryptionTest extends TestCase {
->willReturn(['entry', 'entry']);
$expected = new TemplateResponse(
'settings',
'admin/encryption',
'settings/admin/encryption',
[
'encryptionEnabled' => $enabled,
'encryptionReady' => $enabled,

View file

@ -123,7 +123,7 @@ class ServerTest extends TestCase {
$envPath = getenv('PATH');
$expected = new TemplateResponse(
'settings',
'admin/server',
'settings/admin/server',
[
// Diagnosis
'readOnlyConfigEnabled' => \OC_Helper::isReadOnlyConfigEnabled(),

View file

@ -112,7 +112,7 @@ class SharingTest extends TestCase {
$expected = new TemplateResponse(
'settings',
'admin/sharing',
'settings/admin/sharing',
[
'allowGroupSharing' => 'yes',
'allowLinks' => 'yes',
@ -205,7 +205,7 @@ class SharingTest extends TestCase {
$expected = new TemplateResponse(
'settings',
'admin/sharing',
'settings/admin/sharing',
[
'allowGroupSharing' => 'yes',
'allowLinks' => 'yes',

View file

@ -52,7 +52,7 @@ class TipsTrickTest extends TestCase {
$expected = new TemplateResponse(
'settings',
'admin/tipstricks',
'settings/admin/tipstricks',
[
'databaseOverload' => true,
],
@ -71,7 +71,7 @@ class TipsTrickTest extends TestCase {
$expected = new TemplateResponse(
'settings',
'admin/tipstricks',
'settings/admin/tipstricks',
[
'databaseOverload' => false,
],

View file

@ -23,18 +23,23 @@
namespace Tests\Settings;
use OC\Accounts\AccountManager;
use OC\Settings\Admin\Sharing;
use OC\Settings\Manager;
use OC\Settings\Mapper;
use OC\Settings\Personal\Security;
use OC\Settings\Section;
use OCP\App\IAppManager;
use OCP\Encryption\IManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Lock\ILockingProvider;
use Test\TestCase;
@ -61,6 +66,16 @@ class ManagerTest extends TestCase {
private $mapper;
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $url;
/** @var AccountManager|\PHPUnit_Framework_MockObject_MockObject */
private $accountManager;
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
private $groupManager;
/** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
private $l10nFactory;
/** @var \OC_Defaults|\PHPUnit_Framework_MockObject_MockObject */
private $defaults;
/** @var IAppManager */
private $appManager;
public function setUp() {
parent::setUp();
@ -75,6 +90,11 @@ class ManagerTest extends TestCase {
$this->request = $this->createMock(IRequest::class);
$this->mapper = $this->createMock(Mapper::class);
$this->url = $this->createMock(IURLGenerator::class);
$this->accountManager = $this->createMock(AccountManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->l10nFactory = $this->createMock(IFactory::class);
$this->defaults = $this->createMock(\OC_Defaults::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->manager = new Manager(
$this->logger,
@ -86,21 +106,40 @@ class ManagerTest extends TestCase {
$this->lockingProvider,
$this->request,
$this->mapper,
$this->url
$this->url,
$this->accountManager,
$this->groupManager,
$this->l10nFactory,
$this->defaults,
$this->appManager
);
}
public function testSetupSettingsUpdate() {
public function settingsTypeProvider() {
return [
['admin', 'admin_settings'],
['personal', 'personal_settings'],
];
}
/**
* @dataProvider settingsTypeProvider
* @param string $type
* @param string $table
*/
public function testSetupSettingsUpdate($type, $table) {
$className = 'OCA\Files\Settings\Admin';
$this->mapper->expects($this->any())
->method('has')
->with('admin_settings', 'OCA\Files\Settings\Admin')
->with($table, $className)
->will($this->returnValue(true));
$this->mapper->expects($this->once())
->method('update')
->with('admin_settings',
->with($table,
'class',
'OCA\Files\Settings\Admin', [
$className, [
'section' => 'additional',
'priority' => 5
]);
@ -108,19 +147,24 @@ class ManagerTest extends TestCase {
->method('add');
$this->manager->setupSettings([
'admin' => 'OCA\Files\Settings\Admin',
$type => $className,
]);
}
public function testSetupSettingsAdd() {
/**
* @dataProvider settingsTypeProvider
* @param string $type
* @param string $table
*/
public function testSetupSettingsAdd($type, $table) {
$this->mapper->expects($this->any())
->method('has')
->with('admin_settings', 'OCA\Files\Settings\Admin')
->with($table, 'OCA\Files\Settings\Admin')
->will($this->returnValue(false));
$this->mapper->expects($this->once())
->method('add')
->with('admin_settings', [
->with($table, [
'class' => 'OCA\Files\Settings\Admin',
'section' => 'additional',
'priority' => 5
@ -130,7 +174,7 @@ class ManagerTest extends TestCase {
->method('update');
$this->manager->setupSettings([
'admin' => 'OCA\Files\Settings\Admin',
$type => 'OCA\Files\Settings\Admin',
]);
}
@ -167,6 +211,34 @@ class ManagerTest extends TestCase {
], $this->manager->getAdminSections());
}
public function testGetPersonalSections() {
$this->l10n
->expects($this->any())
->method('t')
->will($this->returnArgument(0));
$this->mapper->expects($this->once())
->method('getPersonalSectionsFromDB')
->will($this->returnValue([
['class' => \OCA\WorkflowEngine\Settings\Section::class, 'priority' => 90]
]));
$this->url->expects($this->exactly(3))
->method('imagePath')
->willReturnMap([
['core', 'actions/info.svg', '1'],
['settings', 'password.svg', '2'],
['settings', 'change.svg', '3'],
]);
$this->assertArraySubset([
0 => [new Section('personal-info', 'Personal info', 0, '1')],
5 => [new Section('security', 'Security', 0, '2')],
15 => [new Section('sync-clients', 'Sync clients', 0, '3')],
90 => [\OC::$server->query(\OCA\WorkflowEngine\Settings\Section::class)],
], $this->manager->getPersonalSections());
}
public function testGetAdminSectionsEmptySection() {
$this->l10n
->expects($this->any())
@ -198,6 +270,31 @@ class ManagerTest extends TestCase {
], $this->manager->getAdminSections());
}
public function testGetPersonalSectionsEmptySection() {
$this->l10n
->expects($this->any())
->method('t')
->will($this->returnArgument(0));
$this->mapper->expects($this->once())
->method('getPersonalSectionsFromDB')
->will($this->returnValue([]));
$this->url->expects($this->exactly(3))
->method('imagePath')
->willReturnMap([
['core', 'actions/info.svg', '1'],
['settings', 'password.svg', '2'],
['settings', 'change.svg', '3'],
]);
$this->assertArraySubset([
0 => [new Section('personal-info', 'Personal info', 0, '1')],
5 => [new Section('security', 'Security', 0, '2')],
15 => [new Section('sync-clients', 'Sync clients', 0, '3')],
], $this->manager->getPersonalSections());
}
public function testGetAdminSettings() {
$this->mapper->expects($this->any())
->method('getAdminSettingsFromDB')
@ -207,4 +304,14 @@ class ManagerTest extends TestCase {
0 => [new Sharing($this->config)],
], $this->manager->getAdminSettings('sharing'));
}
public function testGetPersonalSettings() {
$this->mapper->expects($this->any())
->method('getPersonalSettingsFromDB')
->will($this->returnValue([]));
$this->assertEquals([
10 => [new Security()],
], $this->manager->getPersonalSettings('security'));
}
}

View file

@ -26,7 +26,7 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
$OC_Version = array(13, 0, 0, 0);
$OC_Version = array(13, 0, 0, 1);
// The human readable string
$OC_VersionString = '13.0.0 alpha';