Consolidate configuration settings and implement dynamic webui settings (#9809)

* initial db/defaults dump

* numeric values

* Remove $config['time']

* Use config_definitions.json

* try setting definition as a complete array

* a little more

* fix format

* WIP converting dynamic setting pages

* rewriting the webui

* remove legacy and add translations

* finish email section

* improve navigation
update js a bit

* Import the remaining existing settings

* Update backend still some wip
migration

* fix config loading (db not overriding defaults)

* some cleanup

* more array collapsing

* update settings

* Settings search

* add purge settings to ui, order groups and sections

* collapse more arrays

* Auth definitions WIP

* remove needless slash escapes

* add warning to json

* moving settings from defaults.inc

* remove slow_statistics

* Move rrdtool settings to the poller section

* Use translations more consistently

* removing more settings from defaults.inc.php

* show setting name in tooltip

* allow help text to be shown on mobile

* disable settings that are set in config.php

* Implement undo and reset to default.

* Vue.js functional

* Vue.js WIP

* Implement tabs component

* accordion WIP

* lodash ver update

* two items

* Accordion somewhat working

* hash navigation

* Refine Accordion

* Fix up tab styling a bit

* Cleaner tab selected property
Hide html while loading

* spinner?

* Icon support
property for accordion to active

* WIP

* Tabs/Sections from ajax

* Setting Component skeletons

* Dynamic Component resolution

* Basic functionality

* toggle class

* Refactor components

* translate tabs and accordions

* simple array attempt

* improve readonly tooltip

* array styling

* array value editing

* organize snmp info

* Handle initial tab/section in url

* Use Laravel to parse tab/section, dump old

* Draggable array entries

* v-tooltip, for clickable (and touch) help tooltips
disable draggable

* Navigation WIP

* Navigation WIP

* groups computed

* filter settings

* fix event reference

* vue.js i18n initial

* missing description = just setting name

* en fallback

* tidy up the language support and js generation

* persist value to db

* fix issue with 0

* Delete settings from DB instead of setting them to default

* ldap-groups
fixup style

* Default dashboard selection

* fix array of options instead of object

* allow custom validation for settings

* translate options in SettingSelect

* SNMP v3 WIP

* fix setting arrays

* Split persist out of set

* Hook up events for SNMP v3 Auth
correct Config::persist behaviour with arrays

* dependent settings (primitive for now)
actually update the settings values in the LibrenmsSettings component

* more complex "when" behaviour

* remove un-needed seeder

* add poller_modules.cisco-qfp

* remove en.json (disable warning)

* don't set default for log_dir or log_file, otherwise it won't be processed correctly

* Fix module order
add some missing settings

* more config corrections

* correct graphs
correct loading values set to null (although it should have no difference)
remove project_name_version

* Add nfsen settings.  Docs are very confusing, so might have flubbed something
remove option for array definition of select option as numeric indexes messes it up

* Correct more upstream config differences

* Config cleanup after a bunch of merges.

* Fixes

* add version tags to js/css files
remove old js

* Print out full settings list read-only

* Add http_proxy setting
fix indents in config_definitions.json

* repeaters default is 0 (aka 20)

* cleanups

* rewrite the dynamic config docs

* add language docs

* Don't show snmp v3 auth add/remove if disabled by config.php
This commit is contained in:
Tony Murray
2019-10-16 21:22:05 +00:00
committed by GitHub
parent 750b19f3e8
commit 699aa8a042
80 changed files with 77045 additions and 2422 deletions

View File

@@ -1,118 +0,0 @@
<?php
/**
* settings.inc.php
*
* Web page to display settings
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2015 Daniel Preussker <f0o@devilcode.org>
* @copyright 2016 Tony Murray <murraytony@gmail.com>
* @author f0o <f0o@devilcode.org>
*/
?>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<span id="message"></span>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<?php
if (Auth::user()->hasGlobalAdmin()) {
echo '<ul class="nav nav-tabs">';
$pages = dbFetchRows("SELECT DISTINCT `config_group` FROM `config` WHERE `config_group` IS NOT NULL AND `config_group` != ''");
array_unshift($pages, array('config_group' => 'Global')); // Add Global tab
$curr_page = basename($vars['sub'] ?? 'Global');
foreach ($pages as $sub_page) {
$sub_page = $sub_page['config_group'];
$page_name = ucfirst($sub_page) . ' Settings';
echo '<li';
if ($sub_page == $curr_page) {
echo ' class="active"';
}
echo '><a href="';
echo generate_url(array(
'page' => 'settings',
'sub' => $sub_page
));
echo '">' . $page_name . '</a></li>';
}
echo '</ul></div></div><br />';
if ($curr_page != 'Global') {
if (file_exists("includes/html/pages/settings/$curr_page.inc.php")) {
require_once "includes/html/pages/settings/$curr_page.inc.php";
} else {
print_error("This settings page doesn't exist, please go to the main settings page");
}
} else {
/**
* Array-To-Table
* @param array $a N-Dimensional, Associative Array
* @return string
*/
function a2t($a)
{
$excluded = array(
'db_pass',
'email_smtp_password',
'password',
'auth_ad_bindpassword',
);
ksort($a);
$r = '<table class="table table-condensed table-hover"><tbody>';
foreach ($a as $k => $v) {
if (!empty($v)) {
if (!in_array($k, $excluded, true)) {
$r .= '<tr><td class="col-md-2"><i><b>' . $k . '</b></i></td><td class="col-md-10">';
$r .= is_array($v) ? a2t($v) : '<code>' . wordwrap($v, 75, '<br/>') . '</code>';
$r .= '</td></tr>';
}
}
}
$r .= '</tbody></table>';
return $r;
}
echo '<div class="table-responsive">' . a2t(\LibreNMS\Config::getAll()) . '</div>';
if ($debug && Auth::user()->hasGlobalAdmin()) {
echo("<pre>");
print_r(\LibreNMS\Config::getAll());
echo("</pre>");
}
}
} else {
include 'includes/html/error-no-perm.inc.php';
}
?>
</div>

View File

@@ -1,272 +0,0 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
use LibreNMS\Config;
$no_refresh = true;
$config_groups = get_config_by_group('alerting');
if (Config::has('base_url') && filter_var(Config::get('base_url') . '/' . $_SERVER['REQUEST_URI'], FILTER_VALIDATE_URL)) {
$callback = Config::get('base_url') . '/' . $_SERVER['REQUEST_URI'] . '/';
} else {
$callback = get_url().'/';
}
$callback = urlencode($callback);
$general_conf = array(
array('name' => 'alert.disable',
'descr' => 'Disable alerting',
'type' => 'checkbox',
),
array('name' => 'alert.admins',
'descr' => 'Issue alerts to admins',
'type' => 'checkbox',
),
array('name' => 'alert.globals',
'descr' => 'Issue alerts to read only users',
'type' => 'checkbox',
),
array('name' => 'alert.users',
'descr' => 'Issue alerts to normal users',
'type' => 'checkbox',
),
array('name' => 'alert.syscontact',
'descr' => 'Issue alerts to sysContact',
'type' => 'checkbox',
),
array('name' => 'alert.default_only',
'descr' => 'Send alerts to default contact only',
'type' => 'checkbox',
),
array('name' => 'alert.default_copy',
'descr' => 'Copy all email alerts to default contact',
'type' => 'checkbox',
),
array('name' => 'alert.default_mail',
'descr' => 'Default contact',
'type' => 'text',
'pattern' => '[a-zA-Z0-9_\-\.\+]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,18}',
),
array('name' => 'alert.tolerance_window',
'descr' => 'Tolerance window for cron',
'type' => 'numeric',
'required' => true,
),
array('name' => 'alert.fixed-contacts',
'descr' => 'Updates to contact email addresses not honored',
'type' => 'checkbox',
),
[
'name' => 'alert.ack_until_clear',
'descr' => 'Default acknowledge until alert clears option',
'type' => 'checkbox',
]
);
$mail_conf = [
[
'name' => 'alert.transports.mail',
'descr' => 'Enable email alerting',
'type' => 'checkbox',
],
[
'name' => 'email_backend',
'descr' => 'How to deliver mail',
'options' => Config::get('email_backend_options', ['mail', 'sendmail', 'smtp']),
'type' => 'select',
],
[
'name' => 'email_user',
'descr' => 'From name',
'type' => 'text',
],
[
'name' => 'email_from',
'descr' => 'From email address',
'type' => 'text',
'pattern' => '[a-zA-Z0-9_\-\.\+]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,18}',
],
[
'name' => 'email_html',
'descr' => 'Use HTML emails',
'type' => 'checkbox',
],
[
'name' => 'email_sendmail_path',
'descr' => 'Sendmail path',
'type' => 'text',
'class' => 'sendmail-form',
],
[
'name' => 'email_smtp_host',
'descr' => 'SMTP Host',
'type' => 'text',
'pattern' => '[a-zA-Z0-9_\-\.]+',
'class' => 'smtp-form',
],
[
'name' => 'email_smtp_port',
'descr' => 'SMTP Port',
'type' => 'numeric',
'class' => 'smtp-form',
'required' => true,
],
[
'name' => 'email_smtp_timeout',
'descr' => 'SMTP Timeout',
'type' => 'numeric',
'class' => 'smtp-form',
'required' => true,
],
[
'name' => 'email_smtp_secure',
'descr' => 'SMTP Secure',
'type' => 'select',
'class' => 'smtp-form',
'options' => Config::get('email_smtp_secure_options', ['', 'tls', 'ssl']),
],
[
'name' => 'email_auto_tls',
'descr' => 'SMTP Auto TLS Support',
'type' => 'select',
'class' => 'smtp-form',
'options' => ['true', 'false'],
],
[
'name' => 'email_smtp_auth',
'descr' => 'SMTP Authentication',
'type' => 'checkbox',
'class' => 'smtp-form',
],
[
'name' => 'email_smtp_username',
'descr' => 'SMTP Authentication Username',
'type' => 'text',
'class' => 'smtp-form',
],
[
'name' => 'email_smtp_password',
'descr' => 'SMTP Authentication Password',
'type' => 'password',
'class' => 'smtp-form',
],
];
echo '
<div class="panel-group" id="accordion">
<form class="form-horizontal" role="form" action="" method="post">
';
echo csrf_field();
echo generate_dynamic_config_panel('General alert settings', $config_groups, $general_conf);
echo generate_dynamic_config_panel('Email options', $config_groups, $mail_conf);
echo '
</form>
</div>
';
?>
<script>
$(".toolTip").tooltip();
$('#email_backend').change(function () {
var type = this.value;
if (type === 'sendmail') {
$('.smtp-form').hide();
$('.sendmail-form').show();
} else if (type === 'smtp') {
$('.sendmail-form').hide();
$('.smtp-form').show();
} else {
$('.smtp-form').hide();
$('.sendmail-form').hide();
}
}).change(); // trigger initially
apiIndex = 0;
$( 'select[name="global-config-select"]').change(function(event) {
event.preventDefault();
var $this = $(this);
var config_id = $this.data("config_id");
var config_value = $this.val();
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {type: "update-config-item", config_id: config_id, config_value: config_value},
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
$this.closest('.form-group').addClass('has-success');
$this.next().addClass('fa-check');
setTimeout(function(){
$this.closest('.form-group').removeClass('has-success');
$this.next().removeClass('fa-check');
}, 2000);
} else {
$(this).closest('.form-group').addClass('has-error');
$this.next().addClass('fa-times');
setTimeout(function(){
$this.closest('.form-group').removeClass('has-error');
$this.next().removeClass('fa-times');
}, 2000);
}
},
error: function () {
$("#message").html('<div class="alert alert-danger">An error occurred.</div>');
}
});
});
$(document).on('blur', 'textarea[name="global-config-textarea"]', function(event) {
event.preventDefault();
var $this = $(this);
var config_id = $this.data("config_id");
var config_value = $this.val();
var config_type = $this.data("type");
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {type: "update-config-item", action: 'update-textarea', config_type: config_type, config_id: config_id, config_value: config_value},
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
$this.closest('.form-group').addClass('has-success');
$this.next().addClass('fa-check');
setTimeout(function(){
$this.closest('.form-group').removeClass('has-success');
$this.next().removeClass('fa-check');
}, 2000);
} else {
$(this).closest('.form-group').addClass('has-error');
$this.next().addClass('fa-times');
setTimeout(function(){
$this.closest('.form-group').removeClass('has-error');
$this.next().removeClass('fa-times');
}, 2000);
}
},
error: function () {
$("#message").html('<div class="alert alert-danger">An error occurred.</div>');
}
});
});
</script>

View File

@@ -1,127 +0,0 @@
<?php
$no_refresh = true;
$config_groups = get_config_by_group('external');
$location_conf = [
[
'name' => 'geoloc.engine',
'descr' => 'Geocoding Engine',
'type' => 'select',
'options' => [
['value' => 'google', 'description' => 'Google Maps'],
['value' => 'openstreetmap', 'description' => 'OpenStreetMap'],
['value' => 'mapquest', 'description' => 'MapQuest'],
['value' => 'bing', 'description' => 'Bing Maps'],
]
],
[
'name' => 'geoloc.api_key',
'descr' => 'Geocoding API Key',
'type' => 'text',
'class' => 'geoloc_api_key'
],
];
$oxidized_conf = array(
array('name' => 'oxidized.enabled',
'descr' => 'Enable Oxidized support',
'type' => 'checkbox',
),
array('name' => 'oxidized.url',
'descr' => 'URL to your Oxidized API',
'type' => 'text',
'pattern' => '[a-zA-Z0-9]{1,5}://.*',
'required' => true,
),
array('name' => 'oxidized.features.versioning',
'descr' => 'Enable config versioning access',
'type' => 'checkbox',
),
array('name' => 'oxidized.group_support',
'descr' => 'Enable the return of groups to Oxidized',
'type' => 'checkbox',
),
array('name' => 'oxidized.default_group',
'descr' => 'Set the default group returned',
'type' => 'text',
),
array('name' => 'oxidized.reload_nodes',
'descr' => 'Reload Oxidized nodes list, each time a device is added',
'type' => 'checkbox',
),
);
$unixagent_conf = array(
array('name' => 'unix-agent.port',
'descr' => 'Default unix-agent port',
'type' => 'numeric',
'required' => true,
),
array('name' => 'unix-agent.connection-timeout',
'descr' => 'Connection timeout',
'type' => 'numeric',
'required' => true,
),
array('name' => 'unix-agent.read-timeout',
'descr' => 'Read timeout',
'type' => 'numeric',
'required' => true,
),
);
$rrdtool_conf = array(
array('name' => 'rrdtool',
'descr' => 'Path to rrdtool binary',
'type' => 'text',
),
array('name' => 'rrdtool_tune',
'descr' => 'Tune all rrd port files to use max values',
'type' => 'checkbox',
),
array('name' => 'rrd.step',
'descr' => 'Change the rrd step value (default 300)',
'type' => 'numeric',
'required' => true,
),
array('name' => 'rrd.heartbeat',
'descr' => 'Change the rrd heartbeat value (default 600)',
'type' => 'numeric',
'required' => true,
),
);
$peeringdb_conf = array(
array('name' => 'peeringdb.enabled',
'descr' => 'Enable PeeringDB lookup (data is downloaded with daily.sh)',
'type' => 'checkbox',
),
);
echo '
<div class="panel-group" id="accordion">
<form class="form-horizontal" role="form" action="" method="post">
';
echo csrf_field();
echo generate_dynamic_config_panel('Location Geocoding', $config_groups, $location_conf);
echo generate_dynamic_config_panel('Oxidized integration', $config_groups, $oxidized_conf);
echo generate_dynamic_config_panel('Unix-agent integration', $config_groups, $unixagent_conf);
echo generate_dynamic_config_panel('RRDTool Setup', $config_groups, $rrdtool_conf);
echo generate_dynamic_config_panel('PeeringDB Integration', $config_groups, $peeringdb_conf);
?>
</form>
</div>
<script>
$('#geoloc\\.engine').change(function () {
var engine = this.value;
if (engine === 'openstreetmap') {
$('.geoloc_api_key').hide();
} else {
$('.geoloc_api_key').show();
}
}).change(); // trigger initially
</script>

View File

@@ -1,97 +0,0 @@
<?php
$no_refresh = true;
$config_groups = get_config_by_group('webui');
$search_conf = array(
array('name' => 'webui.global_search_result_limit',
'descr' => 'Set the max search result limit',
'type' => 'numeric',
'required' => true,
),
);
$graph_conf = [
[
'name' => 'webui.min_graph_height',
'descr' => 'Set the minimum graph height',
'type' => 'numeric',
'required' => true,
],
[
'name' => 'webui.graph_type',
'descr' => 'Set the graph type',
'type' => 'select',
'options' => [
'png' => 'png',
'svg' => 'svg',
],
],
[
'name' => 'webui.graph_stacked',
'descr' => 'Use stacked graphs',
'type' => 'checkbox',
],
[
'name' => 'webui.dynamic_graphs',
'descr' => 'Enable dynamic graphs',
'type' => 'checkbox',
]
];
$availability_map_conf = array(
array('name' => 'webui.availability_map_compact',
'descr' => 'Availability map compact view',
'type' => 'checkbox',
),
array('name' => 'webui.availability_map_sort_status',
'descr' => 'Sort devices by status',
'type' => 'checkbox',
),
array('name' => 'webui.availability_map_use_device_groups',
'descr' => 'Use device groups filter',
'type' => 'checkbox',
),
array('name' => 'webui.availability_map_box_size',
'descr' => 'Availability box width',
'type' => 'numeric',
),
);
$dashboard_conf = array(
array('name' => 'webui.default_dashboard_id',
'descr' => 'Set global default dashboard id',
'type' => 'select',
'options' => dbFetchRows(
"SELECT 0 as `value`, 'no default dashboard' as `description`
UNION ALL
SELECT `dashboards`.`dashboard_id` as `value`,
CONCAT( `users`.`username`, ':', `dashboards`.`dashboard_name`,
CASE
WHEN `dashboards`.`access` = 1 THEN ' (shared, read-only)'
WHEN `dashboards`.`access` = 2 THEN ' (shared, read-write)'
ELSE ''
END
) as `description`
FROM `dashboards` JOIN `users` ON `users`.`user_id` = `dashboards`.`user_id`
WHERE `dashboards`.`access` > 0;"
),
),
);
echo '
<div class="panel-group" id="accordion">
<form class="form-horizontal" role="form" action="" method="post">
';
echo csrf_field();
echo generate_dynamic_config_panel('Graph settings', $config_groups, $graph_conf);
echo generate_dynamic_config_panel('Search settings', $config_groups, $search_conf);
echo generate_dynamic_config_panel('Availability map settings', $config_groups, $availability_map_conf);
echo generate_dynamic_config_panel('Dashboard settings', $config_groups, $dashboard_conf);
echo '
</form>
</div>
';