summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/theming/lib/Settings/Section.php83
-rw-r--r--apps/theming/tests/ServicesTest.php4
-rw-r--r--apps/theming/tests/Settings/SectionTest.php77
-rw-r--r--core/css/styles.scss8
-rw-r--r--lib/private/Settings/Manager.php5
-rw-r--r--lib/private/Settings/Personal/PersonalInfo.php44
-rw-r--r--lib/private/Settings/Theming/ServerInfo.php121
-rw-r--r--settings/Controller/ServerInfoSettingsController.php67
-rw-r--r--settings/css/_server-info.scss99
-rw-r--r--settings/css/_where-is-your-data.scss10
-rw-r--r--settings/css/settings.scss13
-rw-r--r--settings/img/theming-dark.svg1
-rw-r--r--settings/js/admin.js103
-rw-r--r--settings/routes.php1
-rw-r--r--settings/templates/settings/admin/server-info.php114
-rw-r--r--settings/templates/settings/personal/partials/where-is-your-data.php76
-rw-r--r--settings/templates/settings/personal/personal.info.php10
-rw-r--r--tests/Settings/Controller/ServerInfoSettingsControllerTest.php94
-rw-r--r--tests/lib/Settings/ManagerTest.php12
19 files changed, 762 insertions, 180 deletions
diff --git a/apps/theming/lib/Settings/Section.php b/apps/theming/lib/Settings/Section.php
deleted file mode 100644
index 9ec990ebe48..00000000000
--- a/apps/theming/lib/Settings/Section.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @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\Theming\Settings;
-
-use OCP\IL10N;
-use OCP\IURLGenerator;
-use OCP\Settings\IIconSection;
-
-class Section implements IIconSection {
- /** @var IL10N */
- private $l;
- /** @var IURLGenerator */
- private $url;
-
- /**
- * @param IURLGenerator $url
- * @param IL10N $l
- */
- public function __construct(IURLGenerator $url, IL10N $l) {
- $this->url = $url;
- $this->l = $l;
- }
-
- /**
- * returns the ID of the section. It is supposed to be a lower case string,
- * e.g. 'ldap'
- *
- * @returns string
- */
- public function getID() {
- return 'theming';
- }
-
- /**
- * returns the translated name as it should be displayed, e.g. 'LDAP / AD
- * integration'. Use the L10N service to translate it.
- *
- * @return string
- */
- public function getName() {
- return $this->l->t('Theming');
- }
-
- /**
- * @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
- */
- public function getPriority() {
- return 30;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getIcon() {
- return $this->url->imagePath('theming', 'app-dark.svg');
- }
-}
diff --git a/apps/theming/tests/ServicesTest.php b/apps/theming/tests/ServicesTest.php
index a46e28235f5..baf7c6edc88 100644
--- a/apps/theming/tests/ServicesTest.php
+++ b/apps/theming/tests/ServicesTest.php
@@ -26,13 +26,11 @@ namespace OCA\Theming\Tests;
use OCA\Theming\Capabilities;
use OCA\Theming\Controller\ThemingController;
use OCA\Theming\Settings\Admin;
-use OCA\Theming\Settings\Section;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
use OCP\AppFramework\App;
use OCP\Capabilities\ICapability;
use OCP\IL10N;
-use OCP\Settings\ISection;
use OCP\Settings\ISettings;
use Test\TestCase;
@@ -72,8 +70,6 @@ class ServicesTest extends TestCase {
// Settings
[Admin::class],
[Admin::class, ISettings::class],
- [Section::class],
- [Section::class, ISection::class],
];
}
diff --git a/apps/theming/tests/Settings/SectionTest.php b/apps/theming/tests/Settings/SectionTest.php
deleted file mode 100644
index 09abf9e34f5..00000000000
--- a/apps/theming/tests/Settings/SectionTest.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @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\Theming\Tests\Settings;
-
-use OCA\Theming\Settings\Section;
-use OCP\IL10N;
-use OCP\IURLGenerator;
-use Test\TestCase;
-
-class SectionTest extends TestCase {
- /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
- private $url;
- /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
- private $l;
- /** @var Section */
- private $section;
-
- public function setUp() {
- parent::setUp();
- $this->url = $this->createMock(IURLGenerator::class);
- $this->l = $this->createMock(IL10N::class);
-
- $this->section = new Section(
- $this->url,
- $this->l
- );
- }
-
- public function testGetID() {
- $this->assertSame('theming', $this->section->getID());
- }
-
- public function testGetName() {
- $this->l
- ->expects($this->once())
- ->method('t')
- ->with('Theming')
- ->willReturn('Theming');
-
- $this->assertSame('Theming', $this->section->getName());
- }
-
- public function testGetPriority() {
- $this->assertSame(30, $this->section->getPriority());
- }
-
- public function testGetIcon() {
- $this->url->expects($this->once())
- ->method('imagePath')
- ->with('theming', 'app-dark.svg')
- ->willReturn('icon');
-
- $this->assertSame('icon', $this->section->getIcon());
- }
-}
diff --git a/core/css/styles.scss b/core/css/styles.scss
index 912648f2757..11c737af52f 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -60,11 +60,11 @@ a {
* {
cursor: pointer;
}
-}
-a.external {
- margin: 0 3px;
- text-decoration: underline;
+ &.external {
+ margin: 0 3px;
+ text-decoration: underline;
+ }
}
input {
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
index 42ec16e223b..3f72557d8ec 100644
--- a/lib/private/Settings/Manager.php
+++ b/lib/private/Settings/Manager.php
@@ -192,6 +192,7 @@ class Manager implements IManager {
1 => [new Section('server', $this->l->t('Basic settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))],
10 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('core', 'actions/password.svg'))],
+ 30 => [new Section('theming', $this->l->t('Theming'), 0, $this->url->imagePath('settings', 'theming-dark.svg'))],
50 => [new Section('groupware', $this->l->t('Groupware'), 0, $this->url->imagePath('core', 'places/contacts.svg'))],
98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
];
@@ -237,6 +238,10 @@ class Manager implements IManager {
$form = $this->container->query(Admin\Security::class);
$forms[$form->getPriority()] = [$form];
}
+ if ($section === 'theming') {
+ $form = $this->container->query(Theming\ServerInfo::class);
+ $forms[$form->getPriority()] = [$form];
+ }
if ($section === 'sharing') {
/** @var ISettings $form */
$form = $this->container->query(Admin\Sharing::class);
diff --git a/lib/private/Settings/Personal/PersonalInfo.php b/lib/private/Settings/Personal/PersonalInfo.php
index 98991ce6d40..74969806540 100644
--- a/lib/private/Settings/Personal/PersonalInfo.php
+++ b/lib/private/Settings/Personal/PersonalInfo.php
@@ -26,6 +26,7 @@
namespace OC\Settings\Personal;
use OC\Accounts\AccountManager;
+use OC\Settings\Theming\ServerInfo;
use OCA\FederatedFileSharing\AppInfo\Application;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
@@ -38,6 +39,7 @@ use OCP\IUser;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Settings\ISettings;
+use OCP\Encryption\IManager as EncryptionManager;
class PersonalInfo implements ISettings {
@@ -55,14 +57,18 @@ class PersonalInfo implements ISettings {
private $l10nFactory;
/** @var IL10N */
private $l;
+ /** @var EncryptionManager */
+ private $encryptionManager;
/**
* @param IConfig $config
* @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param AccountManager $accountManager
+ * @param IAppManager $appManager
* @param IFactory $l10nFactory
* @param IL10N $l
+ * @param EncryptionManager $encryptionManager
*/
public function __construct(
IConfig $config,
@@ -71,7 +77,8 @@ class PersonalInfo implements ISettings {
AccountManager $accountManager,
IAppManager $appManager,
IFactory $l10nFactory,
- IL10N $l
+ IL10N $l,
+ EncryptionManager $encryptionManager
) {
$this->config = $config;
$this->userManager = $userManager;
@@ -80,6 +87,7 @@ class PersonalInfo implements ISettings {
$this->appManager = $appManager;
$this->l10nFactory = $l10nFactory;
$this->l = $l;
+ $this->encryptionManager = $encryptionManager;
}
/**
@@ -135,13 +143,41 @@ class PersonalInfo implements ISettings {
'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
'groups' => $this->getGroups($user),
- ] + $messageParameters + $languageParameters + $localeParameters;
-
+ ] + $this->getWhereIsYourDataParams() + $messageParameters + $languageParameters + $localeParameters;
return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
}
/**
+ * Returns the "where is your data" template params.
+ *
+ * @return array
+ */
+ private function getWhereIsYourDataParams(): array {
+
+ $adminContactConfigId = $this->config->getSystemValue(ServerInfo::SETTING_PROVIDER_ADMIN_CONTACT);
+ $adminContact = $this->userManager->get($adminContactConfigId);
+
+ $params = [
+ 'dataLocation' => $this->config->getSystemValue(ServerInfo::SETTING_LOCATION),
+ 'provider' => $this->config->getSystemValue(ServerInfo::SETTING_PROVIDER),
+ 'providerLink' => $this->config->getSystemValue(ServerInfo::SETTING_PROVIDER_WEBSITE),
+ 'providerPrivacyLink' => $this->config->getSystemValue(ServerInfo::SETTING_PROVIDER_PRIVACY_LINK),
+ 'encryptionEnabled' => $this->encryptionManager->isEnabled(),
+ 'adminName' => $adminContact !== null ? $adminContact->getDisplayName() : '',
+ 'adminMail' => $adminContact !== null ? $adminContact->getEMailAddress() : ''
+ ];
+
+ $params['show_where_is_your_data_section'] = empty($params['dataLocation']) === false
+ || empty($params['provider']) === false
+ || $params['encryptionEnabled'] === true
+ || empty($params['adminName']) === false;
+
+ return $params;
+
+ }
+
+ /**
* @return string the section ID, e.g. 'sharing'
* @since 9.1
*/
@@ -202,7 +238,7 @@ class PersonalInfo implements ISettings {
$userLang = $languages['commonlanguages'][$userLangIndex];
// search in the other languages
if ($userLangIndex === false) {
- $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));
+ $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));
$userLang = $languages['languages'][$userLangIndex];
}
// if user language is not available but set somehow: show the actual code as name
diff --git a/lib/private/Settings/Theming/ServerInfo.php b/lib/private/Settings/Theming/ServerInfo.php
new file mode 100644
index 00000000000..ecd2fc418fc
--- /dev/null
+++ b/lib/private/Settings/Theming/ServerInfo.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @author Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @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\Theming;
+
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\Settings\ISettings;
+
+/**
+ * This class describes the server info settings.
+ */
+class ServerInfo implements ISettings {
+
+ const SETTING_LOCATION = 'serverinfo.location';
+ const SETTING_PROVIDER = 'serverinfo.provider';
+ const SETTING_PROVIDER_WEBSITE = 'serverinfo.provider.website';
+ const SETTING_PROVIDER_PRIVACY_LINK = 'serverinfo.provider.privacylink';
+ const SETTING_PROVIDER_ADMIN_CONTACT = 'serverinfo.admincontact';
+
+ /**
+ * @var IConfig
+ */
+ private $config;
+
+ /**
+ * @var IGroupManager
+ */
+ private $groupManager;
+
+ /**
+ * ServerInfo constructor.
+ *
+ * @param IConfig $config
+ * @param IGroupManager $groupManager
+ */
+ public function __construct(IConfig $config, IGroupManager $groupManager) {
+ $this->config = $config;
+ $this->groupManager = $groupManager;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm(): TemplateResponse {
+ $parameters = [
+ 'location' => $this->config->getSystemValue(self::SETTING_LOCATION),
+ 'provider' => $this->config->getSystemValue(self::SETTING_PROVIDER),
+ 'providerWebsite' => $this->config->getSystemValue(self::SETTING_PROVIDER_WEBSITE),
+ 'providerPrivacyLink' => $this->config->getSystemValue(self::SETTING_PROVIDER_PRIVACY_LINK),
+ 'adminUsers' => $this->getAdminListValues(),
+ 'adminContact' => $this->config->getSystemValue(self::SETTING_PROVIDER_ADMIN_CONTACT),
+ ];
+ return new TemplateResponse('settings', 'settings/admin/server-info', $parameters, '');
+ }
+
+ /**
+ * Returns the admin list values.
+ *
+ * @return array[] An array or arrays with the keys 'id' and 'displayName'
+ */
+ private function getAdminListValues(): array {
+ $adminGroup = $this->groupManager->get('admin');
+ $users = $adminGroup->getUsers();
+
+ $users = array_map(function(IUser $user) {
+ return [
+ 'id' => $user->getUID(),
+ 'displayName' => $user->getDisplayName()
+ ];
+ }, $users);
+
+ usort($your_data, function(array $a, array $b) {
+ return strcmp($a['displayName'], $b['displayName']);
+ });
+
+ return $users;
+ }
+
+ /**
+ * Returns the server info section id.
+ *
+ * @return string
+ */
+ public function getSection(): string {
+ return 'theming';
+ }
+
+ /**
+ * Returns the server info settings priority.
+ *
+ * @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.
+ */
+ public function getPriority(): int {
+ return 10;
+ }
+
+}
diff --git a/settings/Controller/ServerInfoSettingsController.php b/settings/Controller/ServerInfoSettingsController.php
new file mode 100644
index 00000000000..a5c80211712
--- /dev/null
+++ b/settings/Controller/ServerInfoSettingsController.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @author Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @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 OC\Settings\Theming\ServerInfo;
+use OCP\AppFramework\Controller;
+use OCP\IConfig;
+use OCP\IRequest;
+
+/**
+ * This controller handles server info settings requests.
+ */
+class ServerInfoSettingsController extends Controller {
+
+ /**
+ * @var IConfig
+ */
+ private $config;
+
+ /**
+ * ServerInfoSettingsController constructor.
+ *
+ * @param IConfig $config
+ */
+ public function __construct($appName, IRequest $request, IConfig $config) {
+ parent::__construct($appName, $request);
+ $this->config = $config;
+ }
+
+ public function storeServerInfo(
+ string $location,
+ string $provider,
+ string $providerWebsite,
+ string $providerPrivacyLink,
+ string $adminContact
+ ): void {
+ $configs = [
+ ServerInfo::SETTING_LOCATION => $location,
+ ServerInfo::SETTING_PROVIDER => $provider,
+ ServerInfo::SETTING_PROVIDER_WEBSITE => $providerWebsite,
+ ServerInfo::SETTING_PROVIDER_PRIVACY_LINK => $providerPrivacyLink,
+ ServerInfo::SETTING_PROVIDER_ADMIN_CONTACT => $adminContact
+ ];
+ $this->config->setSystemValues($configs);
+ }
+
+}
diff --git a/settings/css/_server-info.scss b/settings/css/_server-info.scss
new file mode 100644
index 00000000000..1073cab2954
--- /dev/null
+++ b/settings/css/_server-info.scss
@@ -0,0 +1,99 @@
+/* Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
+.server-info-settings {
+ .label {
+ display: block;
+ }
+
+ .form-input {
+ margin-bottom: 10px;
+ width: 100%;
+ }
+
+ .margin-bottom {
+ margin-bottom: 15px;
+ }
+
+ .form-actions {
+ text-align: right;
+
+ .button {
+ align-items: center;
+ display: inline-flex;
+ margin: 0;
+ transition: background-color 500ms linear;
+
+ .default-label,
+ .working-label,
+ .success-label,
+ .error-label {
+ align-items: center;
+ gap: 4px;
+ }
+
+ .working-label,
+ .success-label,
+ .error-label {
+ display: none;
+ }
+ }
+
+ .button-working,
+ .button-success,
+ .button-error {
+ background-color: $color-background-dark;
+ color: $color-text-lighter;
+ opacity: 1;
+
+ .default-label {
+ display: none;
+ }
+ }
+
+ .button-working {
+ .working-label {
+ display: inline-flex;
+ }
+ }
+
+ .button-success {
+ background-color: $color-success;
+ border-color: darken($color-success, 10%);
+ color: $color-primary-text-dark;
+
+ .success-label {
+ display: inline-flex;
+ }
+ }
+
+ .button-error {
+ background-color: $color-error;
+ border-color: darken($color-error, 10%);
+ color: $color-primary-text-dark;
+
+ .error-label {
+ display: inline-flex;
+ }
+ }
+ }
+
+ @media (min-width: 1000px) {
+ .label {
+ display: inline-block;
+ text-align: right;
+ width: 175px;
+ }
+
+ .form-input {
+ margin-left: 5px;
+ width: 225px;
+ }
+
+ .form-actions {
+ margin-left: 180px;
+ width: 225px;
+ }
+ }
+}
diff --git a/settings/css/_where-is-your-data.scss b/settings/css/_where-is-your-data.scss
new file mode 100644
index 00000000000..fc71bb0a023
--- /dev/null
+++ b/settings/css/_where-is-your-data.scss
@@ -0,0 +1,10 @@
+/* Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
+.where-is-your-data {
+ // @todo replace by common link style as soon as available
+ a:not(.icon-info) {
+ border-bottom: 1px dotted;
+ }
+}
diff --git a/settings/css/settings.scss b/settings/css/settings.scss
index 126d451fc66..ebd1ff1b0ec 100644
--- a/settings/css/settings.scss
+++ b/settings/css/settings.scss
@@ -2,6 +2,9 @@
This file is licensed under the Affero General Public License version 3 or later.
See the COPYING-README file. */
+@import "server-info";
+@import "where-is-your-data";
+
input {
&#openid, &#webdav {
width: 20em;
@@ -98,6 +101,7 @@ input {
#personal-settings-avatar-container {
display: inline-grid;
+ grid-row: span 3;
grid-template-columns: 1fr;
grid-template-rows: 2fr 1fr;
vertical-align: top;
@@ -178,6 +182,15 @@ select {
grid-template-columns: 1fr;
#personal-settings-avatar-container {
grid-template-rows: 1fr;
+
+ // swap "Where is my data" and "Detail"
+ *:nth-child(2) {
+ order: 3;
+ }
+
+ *:nth-child(3) {
+ order: 2;
+ }
}
.personal-settings-container {
grid-template-columns: 1fr 1fr;
diff --git a/settings/img/theming-dark.svg b/settings/img/theming-dark.svg
new file mode 100644
index 00000000000..adf97966c41
--- /dev/null
+++ b/settings/img/theming-dark.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 11.412l-.587-.587-.03-.03a.513.513 0 0 1-.074-.526L13.07 3.4l-1.5-1.498-.15.15-.708-.706.505-.505a.538.538 0 0 1 .224-.128c.04-.01.05-.01.087-.016h.087c.04.006.05.006.086.016.072.02.134.055.192.1.74.676 1.42 1.415 2.127 2.124a.503.503 0 0 1 .103.556l-3.053 6.87.344.343.49-.49 3.01 3.01a1.192 1.192 0 0 1-1.685 1.686l-3.012-3.01.49-.488zm-.533-10.217a.986.986 0 0 0-1.396 0l-7.582 7.58a.99.99 0 0 0 0 1.398l1.397 1.396a.986.986 0 0 0 1.396 0l7.58-7.583a.988.988 0 0 0 0-1.396l-1.396-1.395z" fill="#000"/></svg>
diff --git a/settings/js/admin.js b/settings/js/admin.js
index b93c55a8a9c..1c9b5460eab 100644
--- a/settings/js/admin.js
+++ b/settings/js/admin.js
@@ -313,4 +313,107 @@ $(document).ready(function(){
if (document.getElementById('security-warning') !== null) {
setupChecks();
}
+
+ // server info
+
+ var serverInfoForm = $('#server-info-form');
+ var serverInfoWorkingTimeoutHandle;
+ var serverInfoSubmitButton = $('#server-info-submit-button');
+
+ /**
+ * Sets the server info submit button state to default.
+ */
+ function setServerInfoButtonDefault() {
+ serverInfoSubmitButton.removeClass('button-success');
+ serverInfoSubmitButton.removeClass('button-error');
+ serverInfoSubmitButton.removeClass('button-working');
+ }
+
+ /**
+ * Sets the server info submit button state to working.
+ */
+ function setServerInfoButtonWorking() {
+ serverInfoSubmitButton.removeClass('button-success');
+ serverInfoSubmitButton.removeClass('button-error');
+ serverInfoSubmitButton.addClass('button-working');
+ }
+
+ /**
+ * Sets the server info submit button state to success.
+ */
+ function setServerInfoButtonSuccess() {
+ serverInfoSubmitButton.removeClass('button-error');
+ serverInfoSubmitButton.removeClass('button-working');
+ serverInfoSubmitButton.addClass('button-success');
+ }
+
+ /**
+ * Sets the server info submit button state to error.
+ */
+ function setServerInfoButtonError() {
+ serverInfoSubmitButton.removeClass('button-success');
+ serverInfoSubmitButton.removeClass('button-working');
+ serverInfoSubmitButton.addClass('button-error');
+ }
+
+ /**
+ * Clears the server info working timeout, if present.
+ */
+ function clearServerInfoWorkingTimeout() {
+ if (serverInfoWorkingTimeoutHandle) {
+ clearTimeout(serverInfoWorkingTimeoutHandle);
+ serverInfoWorkingTimeoutHandle = undefined;
+ }
+ }
+
+ /**
+ * Unlocks the server info form, e.g. removing readonly from inputs.
+ */
+ function unlockForm() {
+ serverInfoForm.find('input, select').prop('readonly', false);
+ serverInfoSubmitButton.prop('disabled', false);
+ }
+
+ /**
+ * Resets the submit button state one of the form elements is changed.
+ */
+ serverInfoForm.find('input, select').on('keyup change', function() {
+ setServerInfoButtonDefault();
+ });
+
+ /**
+ * Handles the server info form submit.
+ */
+ serverInfoForm.on('submit', function(event) {
+ event.stopImmediatePropagation();
+ event.preventDefault();
+
+ serverInfoForm.find('input, select').prop('readonly', true);
+ serverInfoSubmitButton.prop('disabled', true);
+
+ clearServerInfoWorkingTimeout();
+
+ // start show spinner only if request takes longer than one second
+ serverInfoWorkingTimeoutHandle = setTimeout(function() {
+ setServerInfoButtonWorking();
+ }, 1000);
+
+ $.ajax({
+ url: OC.generateUrl('/settings/serverinfo'),
+ type: 'POST',
+ data: serverInfoForm.serialize(),
+ success: function() {
+ clearServerInfoWorkingTimeout();
+ setServerInfoButtonSuccess();
+ unlockForm();
+ serverInfoSubmitButton.blur();
+ },
+ error: function() {
+ clearServerInfoWorkingTimeout();
+ setServerInfoButtonError();
+ unlockForm();
+ serverInfoSubmitButton.blur();
+ }
+ });
+ });
});
diff --git a/settings/routes.php b/settings/routes.php
index 7c8120f9be4..277bcca484f 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -83,6 +83,7 @@ $application->registerRoutes($this, [
['name' => 'ChangePassword#changeUserPassword', 'url' => '/settings/users/changepassword', 'verb' => 'POST'],
['name' => 'TwoFactorSettings#index', 'url' => '/settings/api/admin/twofactorauth', 'verb' => 'GET'],
['name' => 'TwoFactorSettings#update', 'url' => '/settings/api/admin/twofactorauth', 'verb' => 'PUT'],
+ ['name' => 'ServerInfoSettings#storeServerInfo', 'url' => '/settings/serverinfo', 'verb' => 'POST'],
]
]);
diff --git a/settings/templates/settings/admin/server-info.php b/settings/templates/settings/admin/server-info.php
new file mode 100644
index 00000000000..ac6cf48ee80
--- /dev/null
+++ b/settings/templates/settings/admin/server-info.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @author Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @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/>.
+ */
+
+/**
+ * This file contains the server info settings template.
+ */
+
+/** @var array $_ */
+
+?>
+
+<div class="section server-info-settings">
+ <h2><?php p($l->t('Server info')); ?></h2>
+ <p class="settings-hint">
+ <?php p($l->t('Enter common info about your Nextcloud instance here. These info are visible to all users.')) ?>
+ </p>
+ <form id="server-info-form" name="server-info-form">
+ <div class="margin-bottom">
+ <label class="label" for="location"><?php p($l->t('Server location')); ?></label>
+ <input
+ class="form-input"
+ id="location"
+ name="location"
+ type="text"
+ maxlength="100"
+ value="<?php p($_['location']); ?>"
+ placeholder="<?php p($l->t('country')); ?>">
+ </div>
+ <div>
+ <label class="label" for="provider"><?php p($l->t('Service provider')); ?></label>
+ <input
+ class="form-input"
+ id="provider"
+ name="provider"
+ type="text"
+ maxlength="100"
+ value="<?php p($_['provider']); ?>"
+ placeholder="<?php p($l->t('company or person')); ?>">
+ </div>
+ <div>
+ <label class="label" for="providerWebsite"><?php p($l->t('Provider website')); ?></label>
+ <input
+ class="form-input"
+ id="providerWebsite"
+ name="providerWebsite"
+ type="url"
+ maxlength="200"
+ value="<?php p($_['providerWebsite']); ?>"
+ placeholder="<?php p($l->t('link to website')); ?>">
+ </div>
+ <div class="margin-bottom">
+ <label class="label" for="providerPrivacyLink"><?php p($l->t('Link to privacy policy')); ?></label>
+ <input
+ class="form-input"
+ id="providerPrivacyLink"
+ name="providerPrivacyLink"
+ type="url"
+ maxlength="200"
+ value="<?php p($_['providerPrivacyLink']); ?>"
+ placeholder="<?php p($l->t('link to privacy policy')); ?>">
+ </div>
+ <div class="margin-bottom">
+ <label class="label" for="adminContact"><?php p($l->t('Admin contact')); ?></label>
+ <select class="form-input" name="adminContact" id="adminContact">
+ <option value=""><?php p($l->t('choose admin contact')); ?></option>
+ <?php foreach($_['adminUsers'] as $adminUser): ?>
+ <option
+ value="<?php p($adminUser['id']); ?>"
+ <?php if ($adminUser['id'] === $_['adminContact']): ?>selected="selected"<?php endif; ?>>
+ <?php p($adminUser['displayName']); ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </div>
+ <div class="form-actions">
+ <button id="server-info-submit-button" class="button">
+ <span class="default-label">
+ <?php p($l->t('save')); ?>
+ </span>
+ <span class="working-label">
+ <span class="icon-loading-small-dark"></span>
+ <?php p($l->t('saving')); ?>
+ </span>
+ <span class="success-label">
+ <span class="icon-checkmark-white"></span>
+ <?php p($l->t('saved')); ?>
+ </span>
+ <span class="error-label">
+ <span class="icon-error-white"></span>
+ <?php p($l->t('error saving settings')); ?>
+ </span>
+ </button>
+ </div>
+ </form>
+</div>
diff --git a/settings/templates/settings/personal/partials/where-is-your-data.php b/settings/templates/settings/personal/partials/where-is-your-data.php
new file mode 100644
index 00000000000..56f261f9c00
--- /dev/null
+++ b/settings/templates/settings/personal/partials/where-is-your-data.php
@@ -0,0 +1,76 @@
+<div class="personal-settings-setting-box personal-settings-group-box section where-is-your-data">
+ <h3>
+ <?php p($l->t('Where is your data?')); ?>
+ <a
+ target="_blank"
+ rel="noreferrer noopener"
+ class="icon-info"
+ title=""
+ href="https://nextcloud.com/yourdata/"
+ data-original-title="Open documentation"></a>
+ </h3>
+ <?php if (empty($_['dataLocation']) === false): ?>
+ <div class="personal-info icon-address">
+ <p>
+ <?php echo $l->t('Your data is located in <b>%s</b>.', [$_['dataLocation']]); ?>
+ </p>
+ </div>
+ <?php endif; ?>
+
+ <?php if (empty($_['provider']) === false): ?>
+ <div class="personal-info icon-home">
+ <p>
+ <?php
+ if (empty($_['providerLink']) === false) {
+ echo $l->t('Your provider is %s%s%s.', [
+ '<a href="' . $_['providerLink'] . '" target="_blank" title="" rel="noreferrer noopener">',
+ $_['provider'],
+ '</a>'
+ ]);
+ } else {
+ echo $l->t('Your provider is %s.', [$_['provider']]);
+ }
+ ?>
+ <?php
+ if (empty($_['providerPrivacyLink']) === false) {
+ echo $l->t('Read the %sprivacy policy%s now.', [
+ '<a href="' . $_['providerPrivacyLink'] . '" target="_blank" title="" rel="noreferrer noopener">',
+ '</a>'
+ ]);
+ }
+ ?>
+ </p>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($_['encryptionEnabled'] === true): ?>
+ <div class="personal-info icon-password">
+ <p>
+ <?php echo $l->t(
+ 'Your files are encrypted with %sserver side encryption%s.',
+ [
+ '<a href="https://nextcloud.com/blog/encryption-in-nextcloud/" target="_blank" title="" rel="noreferrer noopener">',
+ '</a>'
+ ]
+ ); ?>
+ </p>
+ </div>
+ <?php endif; ?>
+
+ <?php if (empty($_['adminName']) === false): ?>
+ <div class="personal-info icon-user-admin">
+ <p>
+ <?php echo $l->t(
+ '%s%s%s is your admin. If you have any issues, %scontact them%s.',
+ [
+ '<a href="mailto:' . $_['adminMail'] . '" target="_blank" title="" rel="noreferrer noopener">',
+ $_['adminName'],
+ '</a>',
+ '<a href="mailto:' . $_['adminMail'] . '" target="_blank" title="" rel="noreferrer noopener">',
+ '</a>'
+ ]
+ ); ?>
+ </p>
+ </div>
+ <?php endif; ?>
+</div>
diff --git a/settings/templates/settings/personal/personal.info.php b/settings/templates/settings/personal/personal.info.php
index d873f6821b8..a6e3eaf345b 100644
--- a/settings/templates/settings/personal/personal.info.php
+++ b/settings/templates/settings/personal/personal.info.php
@@ -95,6 +95,11 @@ script('settings', [
<progress value="<?php p($_['usage_relative']); ?>" max="100"<?php if($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
</div>
</div>
+ <?php
+ if ($_['show_where_is_your_data_section']) {
+ include __DIR__ . '/partials/where-is-your-data.php';
+ }
+ ?>
</div>
<div class="personal-settings-container">
@@ -375,9 +380,4 @@ script('settings', [
</div>
<span class="msg"></span>
</div>
-
- <div id="personal-settings-group-container">
-
- </div>
-
</div>
diff --git a/tests/Settings/Controller/ServerInfoSettingsControllerTest.php b/tests/Settings/Controller/ServerInfoSettingsControllerTest.php
new file mode 100644
index 00000000000..8d2083d0acb
--- /dev/null
+++ b/tests/Settings/Controller/ServerInfoSettingsControllerTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @author Michael Weimann <mail@michael-weimann.eu>
+ *
+ * @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 Settings\Controller;
+
+use OC\Settings\Theming\ServerInfo;
+use OC\Settings\Controller\ServerInfoSettingsController;
+use OCP\IConfig;
+use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+/**
+ * This class provides tests for the server info settings controller.
+ */
+class ServerInfoSettingsControllerTest extends TestCase {
+
+ /**
+ * @var IConfig|MockObject
+ */
+ private $config;
+
+ /**
+ * @var ServerInfoSettingsController
+ */
+ private $controller;
+
+ /**
+ * Does the test setup.
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ $request = $this->getMockBuilder(IRequest::class)->getMock();
+ /* @var IRequest|MockObject $request */
+ $this->config = $this->getMockBuilder(IConfig::class)->getMock();
+ $this->controller = new ServerInfoSettingsController(
+ 'settings',
+ $request,
+ $this->config
+ );
+ }
+
+ /**
+ * Tests that the handler passes the params to the config.
+ */
+ public function testStoreServerInfo() {
+
+ $location = 'test-location';
+ $provider = 'test-provider';
+ $providerWebsite = 'https://example.com/';
+ $providerPrivacyLink = 'https://example.com/privacy';
+ $adminContact = 'testuser';
+
+ $this->config->expects($this->once())
+ ->method('setSystemValues')
+ ->with([
+ ServerInfo::SETTING_LOCATION => $location,
+ ServerInfo::SETTING_PROVIDER => $provider,
+ ServerInfo::SETTING_PROVIDER_WEBSITE => $providerWebsite,
+ ServerInfo::SETTING_PROVIDER_PRIVACY_LINK => $providerPrivacyLink,
+ ServerInfo::SETTING_PROVIDER_ADMIN_CONTACT => $adminContact,
+ ]);
+
+ $this->controller->storeServerInfo(
+ $location,
+ $provider,
+ $providerWebsite,
+ $providerPrivacyLink,
+ $adminContact
+ );
+
+ }
+
+}
diff --git a/tests/lib/Settings/ManagerTest.php b/tests/lib/Settings/ManagerTest.php
index b82fb5bc3ca..8323452934f 100644
--- a/tests/lib/Settings/ManagerTest.php
+++ b/tests/lib/Settings/ManagerTest.php
@@ -72,13 +72,14 @@ class ManagerTest extends TestCase {
$this->manager->registerSection('admin', \OCA\WorkflowEngine\Settings\Section::class);
- $this->url->expects($this->exactly(6))
+ $this->url->expects($this->exactly(7))
->method('imagePath')
->willReturnMap([
['settings', 'admin.svg', '0'],
['core', 'actions/settings-dark.svg', '1'],
['core', 'actions/share.svg', '2'],
['core', 'actions/password.svg', '3'],
+ ['settings', 'theming-dark.svg', '6'],
['core', 'places/contacts.svg', '5'],
['settings', 'help.svg', '4'],
]);
@@ -88,6 +89,7 @@ class ManagerTest extends TestCase {
1 => [new Section('server', 'Basic settings', 0, '1')],
5 => [new Section('sharing', 'Sharing', 0, '2')],
10 => [new Section('security', 'Security', 0, '3')],
+ 30 => [new Section('theming', 'Theming', 0, '6')],
50 => [new Section('groupware', 'Groupware', 0, '5')],
55 => [\OC::$server->query(\OCA\WorkflowEngine\Settings\Section::class)],
98 => [new Section('additional', 'Additional settings', 0, '1')],
@@ -124,13 +126,14 @@ class ManagerTest extends TestCase {
->method('t')
->will($this->returnArgument(0));
- $this->url->expects($this->exactly(6))
+ $this->url->expects($this->exactly(7))
->method('imagePath')
->willReturnMap([
['settings', 'admin.svg', '0'],
['core', 'actions/settings-dark.svg', '1'],
['core', 'actions/share.svg', '2'],
['core', 'actions/password.svg', '3'],
+ ['settings', 'theming-dark.svg', '6'],
['core', 'places/contacts.svg', '5'],
['settings', 'help.svg', '4'],
]);
@@ -140,6 +143,7 @@ class ManagerTest extends TestCase {
1 => [new Section('server', 'Basic settings', 0, '1')],
5 => [new Section('sharing', 'Sharing', 0, '2')],
10 => [new Section('security', 'Security', 0, '3')],
+ 30 => [new Section('theming', 'Theming', 0, '6')],
50 => [new Section('groupware', 'Groupware', 0, '5')],
98 => [new Section('additional', 'Additional settings', 0, '1')],
], $this->manager->getAdminSections());
@@ -209,7 +213,7 @@ class ManagerTest extends TestCase {
$this->manager->registerSection('personal', \OCA\WorkflowEngine\Settings\Section::class);
$this->manager->registerSection('admin', \OCA\WorkflowEngine\Settings\Section::class);
- $this->url->expects($this->exactly(9))
+ $this->url->expects($this->exactly(10))
->method('imagePath')
->willReturnMap([
['core', 'actions/info.svg', '1'],
@@ -219,6 +223,7 @@ class ManagerTest extends TestCase {
['core', 'actions/settings-dark.svg', '1'],
['core', 'actions/share.svg', '2'],
['core', 'actions/password.svg', '3'],
+ ['settings', 'theming-dark.svg', '6'],
['core', 'places/contacts.svg', '5'],
['settings', 'help.svg', '4'],
]);
@@ -235,6 +240,7 @@ class ManagerTest extends TestCase {
1 => [new Section('server', 'Basic settings', 0, '1')],
5 => [new Section('sharing', 'Sharing', 0, '2')],
10 => [new Section('security', 'Security', 0, '3')],
+ 30 => [new Section('theming', 'Theming', 0, '6')],
50 => [new Section('groupware', 'Groupware', 0, '5')],
55 => [\OC::$server->query(\OCA\WorkflowEngine\Settings\Section::class)],
98 => [new Section('additional', 'Additional settings', 0, '1')],