diff options
71 files changed, 2439 insertions, 741 deletions
diff --git a/apps/encryption/appinfo/app.php b/apps/encryption/appinfo/app.php index 22c35f87913..950166dca2b 100644 --- a/apps/encryption/appinfo/app.php +++ b/apps/encryption/appinfo/app.php @@ -31,5 +31,4 @@ $app = new Application([], $encryptionSystemReady); if ($encryptionSystemReady) { $app->registerEncryptionModule(); $app->registerHooks(); - $app->registerSettings(); } diff --git a/apps/encryption/appinfo/info.xml b/apps/encryption/appinfo/info.xml index 36b6774c6ec..7cfdc934386 100644 --- a/apps/encryption/appinfo/info.xml +++ b/apps/encryption/appinfo/info.xml @@ -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> diff --git a/apps/encryption/lib/AppInfo/Application.php b/apps/encryption/lib/AppInfo/Application.php index a43646d86d9..56c2dafdabd 100644 --- a/apps/encryption/lib/AppInfo/Application.php +++ b/apps/encryption/lib/AppInfo/Application.php @@ -266,9 +266,4 @@ class Application extends \OCP\AppFramework\App { ); } - - public function registerSettings() { - // Register settings scripts - App::registerPersonal('encryption', 'settings/settings-personal'); - } } diff --git a/apps/encryption/lib/Settings/Personal.php b/apps/encryption/lib/Settings/Personal.php new file mode 100644 index 00000000000..5b01c224538 --- /dev/null +++ b/apps/encryption/lib/Settings/Personal.php @@ -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; + } +} diff --git a/apps/encryption/settings/settings-personal.php b/apps/encryption/settings/settings-personal.php deleted file mode 100644 index 66083408881..00000000000 --- a/apps/encryption/settings/settings-personal.php +++ /dev/null @@ -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; - diff --git a/apps/federatedfilesharing/appinfo/app.php b/apps/federatedfilesharing/appinfo/app.php index b6a145bcc2c..62265ff0644 100644 --- a/apps/federatedfilesharing/appinfo/app.php +++ b/apps/federatedfilesharing/appinfo/app.php @@ -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); diff --git a/apps/federatedfilesharing/appinfo/info.xml b/apps/federatedfilesharing/appinfo/info.xml index aaacf3ec80e..ce2e2286be3 100644 --- a/apps/federatedfilesharing/appinfo/info.xml +++ b/apps/federatedfilesharing/appinfo/info.xml @@ -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> diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php index 346d3c4e292..a2e2f761862 100644 --- a/apps/federatedfilesharing/lib/AppInfo/Application.php +++ b/apps/federatedfilesharing/lib/AppInfo/Application.php @@ -70,13 +70,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 * * @return FederatedShareProvider diff --git a/apps/federatedfilesharing/lib/Settings/Personal.php b/apps/federatedfilesharing/lib/Settings/Personal.php new file mode 100644 index 00000000000..854f5f13ab6 --- /dev/null +++ b/apps/federatedfilesharing/lib/Settings/Personal.php @@ -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; + } +} diff --git a/apps/federatedfilesharing/lib/Settings/PersonalSection.php b/apps/federatedfilesharing/lib/Settings/PersonalSection.php new file mode 100644 index 00000000000..330a4efd7f5 --- /dev/null +++ b/apps/federatedfilesharing/lib/Settings/PersonalSection.php @@ -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; + } +} diff --git a/apps/federatedfilesharing/settings-personal.php b/apps/federatedfilesharing/settings-personal.php deleted file mode 100644 index cd22cc17089..00000000000 --- a/apps/federatedfilesharing/settings-personal.php +++ /dev/null @@ -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(); diff --git a/apps/federatedfilesharing/templates/settings-personal.php b/apps/federatedfilesharing/templates/settings-personal.php index 126daae27d0..c6be2a45f16 100644 --- a/apps/federatedfilesharing/templates/settings-personal.php +++ b/apps/federatedfilesharing/templates/settings-personal.php @@ -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; ?> diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index ddf609129f6..250cbbd00d1 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -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 [ diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml index 5772b89ba9e..74cb3e64e43 100644 --- a/apps/files_external/appinfo/info.xml +++ b/apps/files_external/appinfo/info.xml @@ -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> diff --git a/apps/files_external/lib/AppInfo/Application.php b/apps/files_external/lib/AppInfo/Application.php index fcf10adb375..0bbb81dfea2 100644 --- a/apps/files_external/lib/AppInfo/Application.php +++ b/apps/files_external/lib/AppInfo/Application.php @@ -65,24 +65,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} */ public function getBackends() { diff --git a/apps/files_external/lib/Settings/Personal.php b/apps/files_external/lib/Settings/Personal.php new file mode 100644 index 00000000000..946ba9f6944 --- /dev/null +++ b/apps/files_external/lib/Settings/Personal.php @@ -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; + } + +} diff --git a/apps/files_external/lib/Settings/PersonalSection.php b/apps/files_external/lib/Settings/PersonalSection.php new file mode 100644 index 00000000000..32a841c420a --- /dev/null +++ b/apps/files_external/lib/Settings/PersonalSection.php @@ -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; + } + } +}
\ No newline at end of file diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php deleted file mode 100644 index e2131252384..00000000000 --- a/apps/files_external/personal.php +++ /dev/null @@ -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(); diff --git a/apps/twofactor_backupcodes/appinfo/info.xml b/apps/twofactor_backupcodes/appinfo/info.xml index 92300320e1e..7faf2825bed 100644 --- a/apps/twofactor_backupcodes/appinfo/info.xml +++ b/apps/twofactor_backupcodes/appinfo/info.xml @@ -28,4 +28,8 @@ <step>OCA\TwoFactorBackupCodes\Migration\CopyEntriesFromOldTable</step> </post-migration> </repair-steps> + + <settings> + <personal>OCA\TwoFactorBackupCodes\Settings\Personal</personal> + </settings> </info> diff --git a/apps/twofactor_backupcodes/lib/AppInfo/Application.php b/apps/twofactor_backupcodes/lib/AppInfo/Application.php index ad92c0b1476..050473f7efe 100644 --- a/apps/twofactor_backupcodes/lib/AppInfo/Application.php +++ b/apps/twofactor_backupcodes/lib/AppInfo/Application.php @@ -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'); - } } diff --git a/apps/twofactor_backupcodes/lib/Settings/Personal.php b/apps/twofactor_backupcodes/lib/Settings/Personal.php new file mode 100644 index 00000000000..eb28dacb42b --- /dev/null +++ b/apps/twofactor_backupcodes/lib/Settings/Personal.php @@ -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; + } +} diff --git a/apps/twofactor_backupcodes/settings/personal.php b/apps/twofactor_backupcodes/settings/personal.php deleted file mode 100644 index 48c84a3355e..00000000000 --- a/apps/twofactor_backupcodes/settings/personal.php +++ /dev/null @@ -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 diff --git a/db_structure.xml b/db_structure.xml index 583e9bb8522..ac7f4b3c71b 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -2136,6 +2136,127 @@ </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> diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 33b96d29ac6..db03e49009c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -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', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 6f93d83c316..65b3b9a3cfd 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -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', diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 300c24ff940..16552005931 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -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') { diff --git a/lib/private/Server.php b/lib/private/Server.php index 489683aa127..d10da38d299 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -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; }); diff --git a/lib/private/Settings/Admin/Additional.php b/lib/private/Settings/Admin/Additional.php index ffa0de68488..57bb382c1fa 100644 --- a/lib/private/Settings/Admin/Additional.php +++ b/lib/private/Settings/Admin/Additional.php @@ -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, ''); } /** diff --git a/lib/private/Settings/Admin/Encryption.php b/lib/private/Settings/Admin/Encryption.php index 63020c6bce7..7ee4bafbfeb 100644 --- a/lib/private/Settings/Admin/Encryption.php +++ b/lib/private/Settings/Admin/Encryption.php @@ -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, ''); } /** diff --git a/lib/private/Settings/Admin/Server.php b/lib/private/Settings/Admin/Server.php index 5443336669f..994d927aff0 100644 --- a/lib/private/Settings/Admin/Server.php +++ b/lib/private/Settings/Admin/Server.php @@ -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, ''); } /** diff --git a/lib/private/Settings/Admin/ServerDevNotice.php b/lib/private/Settings/Admin/ServerDevNotice.php index 39897d5c612..017113fd9ca 100644 --- a/lib/private/Settings/Admin/ServerDevNotice.php +++ b/lib/private/Settings/Admin/ServerDevNotice.php @@ -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'); } /** diff --git a/lib/private/Settings/Admin/Sharing.php b/lib/private/Settings/Admin/Sharing.php index 8f57f77b20a..997a4d66581 100644 --- a/lib/private/Settings/Admin/Sharing.php +++ b/lib/private/Settings/Admin/Sharing.php @@ -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, ''); } /** diff --git a/lib/private/Settings/Admin/TipsTricks.php b/lib/private/Settings/Admin/TipsTricks.php index fd0fd595844..0df690dbbeb 100644 --- a/lib/private/Settings/Admin/TipsTricks.php +++ b/lib/private/Settings/Admin/TipsTricks.php @@ -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, ''); } /** diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index d40dfd1e417..db147e05eb9 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -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,16 +286,35 @@ 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) { @@ -338,6 +399,47 @@ class Manager implements IManager { } /** + * @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 */ public function getAdminSettings($section) { @@ -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; + } } diff --git a/lib/private/Settings/Mapper.php b/lib/private/Settings/Mapper.php index 2525f2c9854..3219a812cd5 100644 --- a/lib/private/Settings/Mapper.php +++ b/lib/private/Settings/Mapper.php @@ -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(); diff --git a/lib/private/Settings/Personal/Additional.php b/lib/private/Settings/Personal/Additional.php new file mode 100644 index 00000000000..b2bb26dc6bf --- /dev/null +++ b/lib/private/Settings/Personal/Additional.php @@ -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'; + } +} diff --git a/lib/private/Settings/Personal/PersonalInfo.php b/lib/private/Settings/Personal/PersonalInfo.php new file mode 100644 index 00000000000..fb1f388c599 --- /dev/null +++ b/lib/private/Settings/Personal/PersonalInfo.php @@ -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; + } + +} diff --git a/lib/private/Settings/Personal/Security.php b/lib/private/Settings/Personal/Security.php new file mode 100644 index 00000000000..ecbd1199d11 --- /dev/null +++ b/lib/private/Settings/Personal/Security.php @@ -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; + } +} diff --git a/lib/private/Settings/Personal/SyncClients.php b/lib/private/Settings/Personal/SyncClients.php new file mode 100644 index 00000000000..c4efcb63fe5 --- /dev/null +++ b/lib/private/Settings/Personal/SyncClients.php @@ -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; + } +} diff --git a/lib/public/Settings/IManager.php b/lib/public/Settings/IManager.php index a406915ad09..7a24eab3896 100644 --- a/lib/public/Settings/IManager.php +++ b/lib/public/Settings/IManager.php @@ -38,6 +38,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. * @@ -88,6 +98,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 * * @param string $section the section id for which to load the 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); } diff --git a/settings/Controller/AdminSettingsController.php b/settings/Controller/AdminSettingsController.php index 6c915be6f94..33d9cb2c2a3 100644 --- a/settings/Controller/AdminSettingsController.php +++ b/settings/Controller/AdminSettingsController.php @@ -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 - ]; - } } diff --git a/settings/Controller/CommonSettingsTrait.php b/settings/Controller/CommonSettingsTrait.php new file mode 100644 index 00000000000..ac316aa7f48 --- /dev/null +++ b/settings/Controller/CommonSettingsTrait.php @@ -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); +} diff --git a/settings/Controller/PersonalSettingsController.php b/settings/Controller/PersonalSettingsController.php new file mode 100644 index 00000000000..7e2d62961b7 --- /dev/null +++ b/settings/Controller/PersonalSettingsController.php @@ -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(); + } +} diff --git a/settings/css/settings.css b/settings/css/settings.css index 0d68a3b622d..4786af4733f 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -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; +} diff --git a/settings/js/settings/authtoken-init.js b/settings/js/settings/authtoken-init.js new file mode 100644 index 00000000000..953727e39dc --- /dev/null +++ b/settings/js/settings/authtoken-init.js @@ -0,0 +1,7 @@ +$(document).ready(function () { + var collection = new OC.Settings.AuthTokenCollection(); + var view = new OC.Settings.AuthTokenView({ + collection: collection + }); + view.reload(); +}); diff --git a/settings/js/personal.js b/settings/js/settings/personalInfo.js index effce9de07e..306994a7094 100644 --- a/settings/js/personal.js +++ b/settings/js/settings/personalInfo.js @@ -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; diff --git a/settings/personal.php b/settings/personal.php deleted file mode 100644 index fcccbc50556..00000000000 --- a/settings/personal.php +++ /dev/null @@ -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(); diff --git a/settings/routes.php b/settings/routes.php index 048febaa129..12da950ed2f 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -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 diff --git a/settings/templates/admin/additional.php b/settings/templates/settings/additional.php index 2ad2c5af4e5..2ad2c5af4e5 100644 --- a/settings/templates/admin/additional.php +++ b/settings/templates/settings/additional.php diff --git a/settings/templates/admin/additional-mail.php b/settings/templates/settings/admin/additional-mail.php index bce7e5adeee..bce7e5adeee 100644 --- a/settings/templates/admin/additional-mail.php +++ b/settings/templates/settings/admin/additional-mail.php diff --git a/settings/templates/admin/encryption.php b/settings/templates/settings/admin/encryption.php index 1d956a8f7c1..1d956a8f7c1 100644 --- a/settings/templates/admin/encryption.php +++ b/settings/templates/settings/admin/encryption.php diff --git a/settings/templates/admin/server.development.notice.php b/settings/templates/settings/admin/server.development.notice.php index f58258fc0ae..f58258fc0ae 100644 --- a/settings/templates/admin/server.development.notice.php +++ b/settings/templates/settings/admin/server.development.notice.php diff --git a/settings/templates/admin/server.php b/settings/templates/settings/admin/server.php index 8d00d37fe80..8d00d37fe80 100644 --- a/settings/templates/admin/server.php +++ b/settings/templates/settings/admin/server.php diff --git a/settings/templates/admin/sharing.php b/settings/templates/settings/admin/sharing.php index 38071a4bee9..38071a4bee9 100644 --- a/settings/templates/admin/sharing.php +++ b/settings/templates/settings/admin/sharing.php diff --git a/settings/templates/admin/tipstricks.php b/settings/templates/settings/admin/tipstricks.php index c18c7f25f39..c18c7f25f39 100644 --- a/settings/templates/admin/tipstricks.php +++ b/settings/templates/settings/admin/tipstricks.php diff --git a/settings/templates/settings/empty.php b/settings/templates/settings/empty.php new file mode 100644 index 00000000000..0ed8a873d3c --- /dev/null +++ b/settings/templates/settings/empty.php @@ -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 +?> diff --git a/settings/templates/admin/frame.php b/settings/templates/settings/frame.php index 2b234f4cd9b..80737bc6f91 100644 --- a/settings/templates/admin/frame.php +++ b/settings/templates/settings/frame.php @@ -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']; diff --git a/settings/templates/settings/personal/personal.info.php b/settings/templates/settings/personal/personal.info.php new file mode 100644 index 00000000000..db14a4de986 --- /dev/null +++ b/settings/templates/settings/personal/personal.info.php @@ -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 } ?> diff --git a/settings/templates/settings/personal/security.php b/settings/templates/settings/personal/security.php new file mode 100644 index 00000000000..3a324bf8d21 --- /dev/null +++ b/settings/templates/settings/personal/security.php @@ -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> diff --git a/settings/templates/settings/personal/sync-clients.php b/settings/templates/settings/personal/sync-clients.php new file mode 100644 index 00000000000..ac76ef4f592 --- /dev/null +++ b/settings/templates/settings/personal/sync-clients.php @@ -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> diff --git a/tests/Settings/Controller/AdminSettingsControllerTest.php b/tests/Settings/Controller/AdminSettingsControllerTest.php index 6c93bca0d68..51357f67a2d 100644 --- a/tests/Settings/Controller/AdminSettingsControllerTest.php +++ b/tests/Settings/Controller/AdminSettingsControllerTest.php @@ -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() { @@ -63,10 +81,15 @@ class AdminSettingsControllerTest extends TestCase { ->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')); } } diff --git a/tests/acceptance/features/access-levels.feature b/tests/acceptance/features/access-levels.feature index 57998899a57..80170296675 100644 --- a/tests/acceptance/features/access-levels.feature +++ b/tests/acceptance/features/access-levels.feature @@ -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 diff --git a/tests/acceptance/features/bootstrap/SettingsMenuContext.php b/tests/acceptance/features/bootstrap/SettingsMenuContext.php index 1ff5d94e98f..401575c78f0 100644 --- a/tests/acceptance/features/bootstrap/SettingsMenuContext.php +++ b/tests/acceptance/features/bootstrap/SettingsMenuContext.php @@ -67,6 +67,15 @@ class SettingsMenuContext implements Context, ActorAwareInterface { } /** + * @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 */ public function iOpenTheSettingsMenu() { @@ -83,6 +92,14 @@ class SettingsMenuContext implements Context, ActorAwareInterface { } /** + * @When I visit the settings page + */ + public function iVisitTheSettingsPage() { + $this->iOpenTheSettingsMenu(); + $this->actor->find(self::menuItemFor('Settings'), 2)->click(); + } + + /** * @When I log out */ public function iLogOut() { @@ -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) { + } + } + } diff --git a/tests/acceptance/features/core/ElementWrapper.php b/tests/acceptance/features/core/ElementWrapper.php index 6b730903f6c..f6ce176817b 100644 --- a/tests/acceptance/features/core/ElementWrapper.php +++ b/tests/acceptance/features/core/ElementWrapper.php @@ -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() { diff --git a/tests/lib/Settings/Admin/AdditionalTest.php b/tests/lib/Settings/Admin/AdditionalTest.php index 420a7110c13..84c63f3aeb1 100644 --- a/tests/lib/Settings/Admin/AdditionalTest.php +++ b/tests/lib/Settings/Admin/AdditionalTest.php @@ -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', diff --git a/tests/lib/Settings/Admin/EncryptionTest.php b/tests/lib/Settings/Admin/EncryptionTest.php index a282b059c92..a5f483863e6 100644 --- a/tests/lib/Settings/Admin/EncryptionTest.php +++ b/tests/lib/Settings/Admin/EncryptionTest.php @@ -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, diff --git a/tests/lib/Settings/Admin/ServerTest.php b/tests/lib/Settings/Admin/ServerTest.php index f876ae85136..a71aef0178e 100644 --- a/tests/lib/Settings/Admin/ServerTest.php +++ b/tests/lib/Settings/Admin/ServerTest.php @@ -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(), diff --git a/tests/lib/Settings/Admin/SharingTest.php b/tests/lib/Settings/Admin/SharingTest.php index 0bf03559683..d9aa14fecea 100644 --- a/tests/lib/Settings/Admin/SharingTest.php +++ b/tests/lib/Settings/Admin/SharingTest.php @@ -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', diff --git a/tests/lib/Settings/Admin/TipsTricksTest.php b/tests/lib/Settings/Admin/TipsTricksTest.php index 0e8857b56d0..cbecd51ed55 100644 --- a/tests/lib/Settings/Admin/TipsTricksTest.php +++ b/tests/lib/Settings/Admin/TipsTricksTest.php @@ -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, ], diff --git a/tests/lib/Settings/ManagerTest.php b/tests/lib/Settings/ManagerTest.php index 07f7e71feca..6a13b737c8e 100644 --- a/tests/lib/Settings/ManagerTest.php +++ b/tests/lib/Settings/ManagerTest.php @@ -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')); + } } diff --git a/version.php b/version.php index e237770c820..d9e26eafcee 100644 --- a/version.php +++ b/version.php @@ -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'; |