Implement storing and loading the server info

Signed-off-by: Michael Weimann <mail@michael-weimann.eu>
This commit is contained in:
Michael Weimann 2018-12-19 23:13:35 +01:00
parent 6993faaf67
commit 813ff430f1
No known key found for this signature in database
GPG key ID: 34F0524D4DA694A1
9 changed files with 411 additions and 32 deletions

View file

@ -1,25 +1,103 @@
<?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\Admin;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\Settings\ISettings;
/**
* Class ServerInfo
*
* @package OC\Settings\Admin
* 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() {
$parameters = [];
$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() {
$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.
*

View file

@ -26,6 +26,7 @@
namespace OC\Settings\Personal;
use OC\Accounts\AccountManager;
use OC\Settings\Admin\ServerInfo;
use OCA\FederatedFileSharing\AppInfo\Application;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
@ -115,6 +116,9 @@ class PersonalInfo implements ISettings {
$localeParameters = $this->getLocales($user);
$messageParameters = $this->getMessageParameters($userData);
$adminContactConfigId = $this->config->getSystemValue(ServerInfo::SETTING_PROVIDER_ADMIN_CONTACT);
$adminContact = $this->userManager->get($adminContactConfigId);
$parameters = [
'total_space' => $totalSpace,
'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
@ -141,12 +145,12 @@ class PersonalInfo implements ISettings {
'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
'groups' => $this->getGroups($user),
'dataLocation' => 'Germany',
'provider' => 'Mustermann GmbH',
'providerLink' => 'https://www.hetzner.de/',
'providerPrivacyLink' => 'https://www.hetzner.de/rechtliches/datenschutz',
'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' => true || $this->encryptionManager->isEnabled(),
'adminName' => 'Michael Weimann',
'adminMail' => 'mail@michael-weimann.eu'
'adminName' => $adminContact !== null ? $adminContact->getDisplayName() : '',
'adminMail' => $adminContact !== null ? $adminContact->getEMailAddress() : '',
] + $messageParameters + $languageParameters + $localeParameters;
return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');

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\Admin\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
) {
$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

@ -1,3 +1,7 @@
/* 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;

View file

@ -1,3 +1,7 @@
/* 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) {

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

@ -1,11 +1,39 @@
<?php ?>
<?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>
<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
@ -14,6 +42,7 @@
name="location"
type="text"
maxlength="100"
value="<?php p($_['location']); ?>"
placeholder="<?php p($l->t('country')); ?>">
</div>
<div>
@ -24,6 +53,7 @@
name="provider"
type="text"
maxlength="100"
value="<?php p($_['provider']); ?>"
placeholder="<?php p($l->t('company or person')); ?>">
</div>
<div>
@ -34,6 +64,7 @@
name="providerWebsite"
type="url"
maxlength="200"
value="<?php p($_['providerWebsite']); ?>"
placeholder="<?php p($l->t('link to website')); ?>">
</div>
<div class="margin-bottom">
@ -44,24 +75,30 @@
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="admin"><?php p($l->t('Admin contact')); ?></label>
<select class="form-input" name="admin">
<option>Michael Weimann</option>
<option>Max Mustermann</option>
<option>Peter Petrowski</option>
<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="test123" class="button">
<button id="server-info-submit-button" class="button">
<span class="default-label">
<?php p($l->t('Save')); ?>
<?php p($l->t('save')); ?>
</span>
<span class="working-label">
<span class="icon-loading-small-dark"></span>
<?php p($l->t('saving')); ?>
<?php p($l->t('saving')); ?>
</span>
<span class="success-label">
<span class="icon-checkmark-white"></span>
@ -72,19 +109,6 @@
<?php p($l->t('error saving settings')); ?>
</span>
</button>
<script>
const button = $('#test123');
button.on('click', (event) => {
event.stopImmediatePropagation();
event.preventDefault();
button.prop('disabled', true);
button.addClass('button-working');
setTimeout(() => {
button.removeClass('button-working');
button.addClass('button-success');
}, 1500);
});
</script>
</div>
</form>
</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\Admin\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
);
}
}