Merge pull request #13097 from nextcloud/feature/11319/where-is-your-data

Where is your data?
This commit is contained in:
Morris Jobke 2019-02-11 11:13:55 +01:00 committed by GitHub
commit 34dc165132
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 762 additions and 180 deletions

View File

@ -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');
}
}

View File

@ -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],
];
}

View File

@ -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());
}
}

View File

@ -60,11 +60,11 @@ a {
* {
cursor: pointer;
}
}
a.external {
margin: 0 3px;
text-decoration: underline;
&.external {
margin: 0 3px;
text-decoration: underline;
}
}
input {

View File

@ -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);

View File

@ -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,12 +143,40 @@ 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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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>

After

Width:  |  Height:  |  Size: 611 B

View File

@ -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();
}
});
});
});

View File

@ -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'],
]
]);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
);
}
}

View File

@ -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')],