From ad6ec7f72a7d7326859985a8981b9106259f2d8d Mon Sep 17 00:00:00 2001 From: Neil Lathwood Date: Sat, 14 Jul 2018 22:15:43 +0100 Subject: [PATCH] Refactor alert templates to use Laravel Blade templating engine (#8803) * Initial start on new templating support * further updates * more updates * More working version * Last fixes * Small updates * modified test to look for dbname. * Schema update * Added fix for not being able to disable Philips Hue transport * Updated sql file * Updated db_schema * Set myclabs/deep-copy to be 1.7.x version in composer * Fixes from murrant * Forced nikic/php-parser to version 3.1.x in composer * Updated composer to use custom fork of string-blade-compiler + fixed transport use * Updated to always use correct template * Merged legacy and blade templating engines * Removed template type + fixed test-alert.php * Added more template placeholders * Added ability to reference data in templates as $alert->X * Updated docs for templates * Updated db_schema.yaml * Added $alert->builder * Clarify the use of $alert->builder * Fixed the use of $alert->transport * renamed schema file * Added template validation * Small update to fix travis issue * Add Docs text to title bar * Updated amqp to new of version * Consistency in alert rule and template title bars --- LibreNMS/Alert/AlertData.php | 37 ++ LibreNMS/Alert/Template.php | 213 +++++++++++ alerts.php | 2 +- app/Models/AlertTemplate.php | 38 ++ app/Models/AlertTemplateMap.php | 39 ++ composer.json | 13 +- composer.lock | 309 +++++++++------- config/app.php | 3 +- doc/Alerting/Old_Templates.md | 266 ++++++++++++++ doc/Alerting/Templates.md | 337 +++++++++--------- html/ajax_form.php | 4 +- html/includes/forms/alert-rules.inc.php | 6 +- html/includes/forms/alert-templates.inc.php | 39 +- .../forms/parse-alert-template.inc.php | 3 +- html/includes/modal/alert_template.inc.php | 159 +-------- html/includes/modal/new_alert_rule.inc.php | 2 +- html/pages/settings/alerting.inc.php | 1 + html/pages/templates.inc.php | 84 +++++ includes/alerts.inc.php | 124 ++----- includes/common.php | 4 +- includes/dbFacile.php | 6 +- includes/functions.php | 4 +- includes/init.php | 7 + misc/db_schema.yaml | 1 - mkdocs.yml | 1 + scripts/test-alert.php | 3 +- sql-schema/254.sql | 1 + tests/DBSetupTest.php | 2 +- 28 files changed, 1121 insertions(+), 587 deletions(-) create mode 100644 LibreNMS/Alert/AlertData.php create mode 100644 LibreNMS/Alert/Template.php create mode 100644 app/Models/AlertTemplate.php create mode 100644 app/Models/AlertTemplateMap.php create mode 100644 doc/Alerting/Old_Templates.md create mode 100644 sql-schema/254.sql diff --git a/LibreNMS/Alert/AlertData.php b/LibreNMS/Alert/AlertData.php new file mode 100644 index 0000000000..928ded3181 --- /dev/null +++ b/LibreNMS/Alert/AlertData.php @@ -0,0 +1,37 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Alert; + +class AlertData extends \Illuminate\Support\Collection +{ + public function __get($name) + { + if ($this->has($name)) { + return $this->get($name); + } + return "$name is not a valid \$alert data name"; + } +} diff --git a/LibreNMS/Alert/Template.php b/LibreNMS/Alert/Template.php new file mode 100644 index 0000000000..82d5852053 --- /dev/null +++ b/LibreNMS/Alert/Template.php @@ -0,0 +1,213 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Neil Lathwood + * @author Neil Lathwood + */ + +namespace LibreNMS\Alert; + +use App\Models\AlertTemplate; + +class Template +{ + public $template; + + /** + * + * Get the template details + * + * @param null $obj + * @return mixed + */ + public function getTemplate($obj = null) + { + if ($this->template) { + // Return the cached template information. + return $this->template; + } + $this->template = AlertTemplate::whereHas('map', function ($query) use ($obj) { + $query->where('alert_rule_id', '=', $obj['rule_id']); + })->first(); + if (!$this->template) { + $this->template = AlertTemplate::where('name', '=', 'Default Alert Template')->first(); + } + return $this->template; + } + + public function getTitle($data) + { + $data['parsed_title'] = $this->bladeTitle($data); + return $this->legacyTitle($data); + } + + public function getBody($data) + { + $data['template']['parsed_template'] = $this->bladeBody($data); + return $this->legacyBody($data); + } + + /** + * + * Parse Blade body + * + * @param $data + * @return string + */ + public function bladeBody($data) + { + $alert['alert'] = new AlertData($data['alert']); + try { + return view(['template' => $data['template']->template], $alert)->__toString(); + } catch (\Exception $e) { + return view(['template' => $this->getDefaultTemplate($data)], $alert)->__toString(); + } + } + + /** + * + * Parse Blade title + * + * @param $data + * @return string + */ + public function bladeTitle($data) + { + $alert['alert'] = new AlertData($data['alert']); + try { + return view(['template' => $data['title']], $alert)->__toString(); + } catch (\Exception $e) { + return $data['title'] ?: view(['template' => "Template " . $data['name']], $alert)->__toString(); + } + } + + /** + * + * Parse legacy body + * + * @param $data + * @return mixed|string + */ + public function legacyBody($data) + { + $tpl = $data['template']->parsed_template; + $msg = '$ret .= "'.str_replace(array('{else}', '{/if}', '{/foreach}'), array('"; } else { $ret .= "', '"; } $ret .= "', '"; } $ret .= "'), addslashes($tpl)).'";'; + $parsed = $msg; + $s = strlen($msg); + $x = $pos = -1; + $buff = ''; + $if = $for = $calc = false; + while (++$x < $s) { + if ($msg[$x] == '{' && $buff == '') { + $buff .= $msg[$x]; + } elseif ($buff == '{ ') { + $buff = ''; + } elseif ($buff != '') { + $buff .= $msg[$x]; + } + + if ($buff == '{if') { + $pos = $x; + $if = true; + } elseif ($buff == '{foreach') { + $pos = $x; + $for = true; + } elseif ($buff == '{calc') { + $pos = $x; + $calc = true; + } + + if ($pos != -1 && $msg[$x] == '}') { + $orig = $buff; + $buff = ''; + $pos = -1; + if ($if) { + $if = false; + $o = 3; + $native = array( + '"; if( ', + ' ) { $ret .= "', + ); + } elseif ($for) { + $for = false; + $o = 8; + $native = array( + '"; foreach( ', + ' as $key=>$value) { $ret .= "', + ); + } elseif ($calc) { + $calc = false; + $o = 5; + $native = array( + '"; $ret .= (float) (0+(', + ')); $ret .= "', + ); + } else { + continue; + } + + $cond = trim(populate(substr($orig, $o, -1), false)); + $native = $native[0].$cond.$native[1]; + $parsed = str_replace($orig, $native, $parsed); + unset($cond, $o, $orig, $native); + }//end if + }//end while + $parsed = populate($parsed); + return RunJail($parsed, $data); + } + + /** + * + * Parse legacy title + * + * @param $data + * @return mixed|string + */ + public function legacyTitle($data) + { + if (strstr($data['parsed_title'], '%')) { + return RunJail('$ret = "'.populate(addslashes($data['parsed_title'])).'";', $data); + } else { + return $data['parsed_title']; + } + } + + /** + * + * Get the default template + * + * @return string + */ + public function getDefaultTemplate() + { + return '{{ $title }}' . PHP_EOL . + 'Severity: {{ $severity }}' . PHP_EOL . + '@if ($state == 0)Time elapsed: {{ $elapsed }} @endif ' . PHP_EOL . + 'Timestamp: {{ $timestamp }}' . PHP_EOL . + 'Unique-ID: {{ $uid }}' . PHP_EOL . + 'Rule: @if ($name) {{ $name }} @else {{ $rule }} @endif ' . PHP_EOL . + '@if ($faults)Faults:' . PHP_EOL . + '@foreach ($faults as $key => $value)' . PHP_EOL . + ' #{{ $key }}: {{ $value[\'string\'] }} @endforeach' . PHP_EOL . + '@endif' . PHP_EOL . + 'Alert sent to: @foreach ($contacts as $key => $value) {{ $value }} <{{ $key }}> @endforeach'; + } +} diff --git a/alerts.php b/alerts.php index 09b519a46a..1880c0c39f 100755 --- a/alerts.php +++ b/alerts.php @@ -27,7 +27,7 @@ use LibreNMS\Util\FileLock; -$init_modules = array('alerts'); +$init_modules = ['alerts', 'alerts-cli']; require __DIR__ . '/includes/init.php'; $options = getopt('d::'); diff --git a/app/Models/AlertTemplate.php b/app/Models/AlertTemplate.php new file mode 100644 index 0000000000..74a6ea0196 --- /dev/null +++ b/app/Models/AlertTemplate.php @@ -0,0 +1,38 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Neil Lathwood + * @author Neil Lathwood + */ + +namespace App\Models; + +class AlertTemplate extends BaseModel +{ + public $timestamps = false; + + // ---- Define Relationships ---- + + public function map() + { + return $this->hasMany('App\Models\AlertTemplateMap', 'alert_templates_id', 'id'); + } +} diff --git a/app/Models/AlertTemplateMap.php b/app/Models/AlertTemplateMap.php new file mode 100644 index 0000000000..85efc4a0de --- /dev/null +++ b/app/Models/AlertTemplateMap.php @@ -0,0 +1,39 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2018 Neil Lathwood + * @author Neil Lathwood + */ + +namespace App\Models; + +class AlertTemplateMap extends BaseModel +{ + protected $table = 'alert_template_map'; + public $timestamps = false; + + // ---- Define Relationships ---- + + public function template() + { + return $this->belongsTo('App\Models\AlertTemplate', 'alert_templates_id'); + } +} diff --git a/composer.json b/composer.json index ebce12d9ed..3ac018d171 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,13 @@ "issues": "https://github.com/librenms/librenms/issues/", "irc": "irc://irc.freenode.org/#librenms" }, + "repositories": + [ + { + "type": "vcs", + "url": "https://github.com/librenms/StringBladeCompiler" + } + ], "require": { "php": ">=5.6.4", "ext-mysqli": "*", @@ -37,13 +44,15 @@ "influxdb/influxdb-php": "^1.14", "laravel/laravel": "5.4.*", "oriceon/toastr-5-laravel": "dev-master", - "doctrine/inflector": "1.1.*", "symfony/event-dispatcher": "3.*", "symfony/css-selector": "3.*", "doctrine/instantiator": "1.0.*", "phpdocumentor/reflection-docblock": "3.*", - "phpunit/php-token-stream": "1.*" + "phpunit/php-token-stream": "1.*", + "wpb/string-blade-compiler": "3.4.x-dev", + "myclabs/deep-copy": "1.7.*", + "nikic/php-parser": "v3.1.*" }, "require-dev": { "squizlabs/php_codesniffer": "^2.9.1", diff --git a/composer.lock b/composer.lock index d5b07d9bbe..c17259722a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cbaf71886db021d5c8e7e2a04c06361a", + "content-hash": "1ec95b9b21153d67687370be2181ea01", "packages": [ { "name": "amenadiel/jpgraph", - "version": "3.6.19", + "version": "3.6.20", "source": { "type": "git", "url": "https://github.com/HuasoFoundries/jpgraph.git", - "reference": "c9f800a00850706f3fc4b26b6055b55952eb79bc" + "reference": "10a818bc8c1b40deb0063f0f3c3e67c23e3030b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/HuasoFoundries/jpgraph/zipball/c9f800a00850706f3fc4b26b6055b55952eb79bc", - "reference": "c9f800a00850706f3fc4b26b6055b55952eb79bc", + "url": "https://api.github.com/repos/HuasoFoundries/jpgraph/zipball/10a818bc8c1b40deb0063f0f3c3e67c23e3030b7", + "reference": "10a818bc8c1b40deb0063f0f3c3e67c23e3030b7", "shasum": "" }, "require": { @@ -59,7 +59,7 @@ "jpgraph", "pie" ], - "time": "2018-05-18T17:10:05+00:00" + "time": "2018-06-13T13:59:24+00:00" }, { "name": "dapphp/radius", @@ -602,31 +602,24 @@ }, { "name": "influxdb/influxdb-php", - "version": "1.14.5", + "version": "1.14.7", "source": { "type": "git", "url": "https://github.com/influxdata/influxdb-php.git", - "reference": "64c79de3f3e0e7f8c20b5fc51f50da8736767de9" + "reference": "570bd5cdedb9b1c1628dceea5785bc40e08f7e48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/influxdata/influxdb-php/zipball/64c79de3f3e0e7f8c20b5fc51f50da8736767de9", - "reference": "64c79de3f3e0e7f8c20b5fc51f50da8736767de9", + "url": "https://api.github.com/repos/influxdata/influxdb-php/zipball/570bd5cdedb9b1c1628dceea5785bc40e08f7e48", + "reference": "570bd5cdedb9b1c1628dceea5785bc40e08f7e48", "shasum": "" }, "require": { "guzzlehttp/guzzle": "^6.0", - "php": "^5.5 || ^7.0", - "symfony/event-dispatcher": "^2.0 || ^3.0 || ^4.0" + "php": "^5.5 || ^7.0" }, "require-dev": { - "codeclimate/php-test-reporter": "0.*", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/phpunit-bridge": "^3.4 || ^4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/yaml": "~2.8|~3.0|~4.0" + "phpunit/phpunit": "^5.7" }, "suggest": { "stefanotorresi/influxdb-php-async": "An asyncronous client for InfluxDB, implemented via ReactPHP." @@ -665,7 +658,7 @@ "influxdb library", "time series" ], - "time": "2018-01-03T13:09:43+00:00" + "time": "2018-07-06T10:13:39+00:00" }, { "name": "jakub-onderka/php-console-color", @@ -1197,17 +1190,62 @@ "time": "2017-01-23T04:29:33+00:00" }, { - "name": "nesbot/carbon", - "version": "1.29.2", + "name": "myclabs/deep-copy", + "version": "1.7.0", "source": { "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "ed6aa898982f441ccc9b2acdec51490f2bc5d337" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/ed6aa898982f441ccc9b2acdec51490f2bc5d337", - "reference": "ed6aa898982f441ccc9b2acdec51490f2bc5d337", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-10-19T19:58:43+00:00" + }, + { + "name": "nesbot/carbon", + "version": "1.32.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "64563e2b9f69e4db1b82a60e81efa327a30ff343" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/64563e2b9f69e4db1b82a60e81efa327a30ff343", + "reference": "64563e2b9f69e4db1b82a60e81efa327a30ff343", "shasum": "" }, "require": { @@ -1219,6 +1257,13 @@ "phpunit/phpunit": "^4.8.35 || ^5.7" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, "autoload": { "psr-4": { "": "src/" @@ -1242,7 +1287,7 @@ "datetime", "time" ], - "time": "2018-05-29T15:23:46+00:00" + "time": "2018-07-05T06:59:26+00:00" }, { "name": "nikic/php-parser", @@ -1400,16 +1445,16 @@ }, { "name": "paragonie/random_compat", - "version": "v2.0.14", + "version": "v2.0.17", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "f6ce7dd93628088e1017fb5dd73b0b9fec7df9e5" + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/f6ce7dd93628088e1017fb5dd73b0b9fec7df9e5", - "reference": "f6ce7dd93628088e1017fb5dd73b0b9fec7df9e5", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", "shasum": "" }, "require": { @@ -1445,7 +1490,7 @@ "pseudorandom", "random" ], - "time": "2018-06-06T17:40:22+00:00" + "time": "2018-07-04T16:31:37+00:00" }, { "name": "pear/console_color2", @@ -1963,16 +2008,16 @@ }, { "name": "psy/psysh", - "version": "v0.9.5", + "version": "v0.9.6", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "0951e91ac04ca28cf317f3997a0adfc319e80106" + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/0951e91ac04ca28cf317f3997a0adfc319e80106", - "reference": "0951e91ac04ca28cf317f3997a0adfc319e80106", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4a2ce86f199d51b6e2524214dc06835e872f4fce", + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce", "shasum": "" }, "require": { @@ -2031,7 +2076,7 @@ "interactive", "shell" ], - "time": "2018-06-02T16:39:22+00:00" + "time": "2018-06-10T17:57:20+00:00" }, { "name": "ramsey/uuid", @@ -2265,16 +2310,16 @@ }, { "name": "symfony/console", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27" + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/36f83f642443c46f3cf751d4d2ee5d047d757a27", - "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27", + "url": "https://api.github.com/repos/symfony/console/zipball/1b97071a26d028c9bd4588264e101e14f6e7cd00", + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00", "shasum": "" }, "require": { @@ -2330,11 +2375,11 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-05-16T08:49:21+00:00" + "time": "2018-05-23T05:02:55+00:00" }, { "name": "symfony/css-selector", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -2387,16 +2432,16 @@ }, { "name": "symfony/debug", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68" + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/b28fd73fefbac341f673f5efd707d539d6a19f68", - "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68", + "url": "https://api.github.com/repos/symfony/debug/zipball/47e6788c5b151cf0cfdf3329116bf33800632d75", + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75", "shasum": "" }, "require": { @@ -2439,11 +2484,11 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-05-16T14:03:39+00:00" + "time": "2018-06-25T11:10:40+00:00" }, { "name": "symfony/dotenv", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", @@ -2500,7 +2545,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -2563,16 +2608,16 @@ }, { "name": "symfony/finder", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "472a92f3df8b247b49ae364275fb32943b9656c6" + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/472a92f3df8b247b49ae364275fb32943b9656c6", - "reference": "472a92f3df8b247b49ae364275fb32943b9656c6", + "url": "https://api.github.com/repos/symfony/finder/zipball/3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", "shasum": "" }, "require": { @@ -2608,20 +2653,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-05-16T08:49:21+00:00" + "time": "2018-06-19T20:52:10+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a7b5fc605d1c215cea1122359044b1e682eb70c0" + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a7b5fc605d1c215cea1122359044b1e682eb70c0", - "reference": "a7b5fc605d1c215cea1122359044b1e682eb70c0", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", "shasum": "" }, "require": { @@ -2662,20 +2707,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-05-25T11:07:31+00:00" + "time": "2018-06-21T11:10:19+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3dac45df55ee0c5134c457a730cd68e2a2ce0445" + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3dac45df55ee0c5134c457a730cd68e2a2ce0445", - "reference": "3dac45df55ee0c5134c457a730cd68e2a2ce0445", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cb7edcdc47cab3c61c891e6e55337f8dd470d820", + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820", "shasum": "" }, "require": { @@ -2683,7 +2728,7 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4", + "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -2751,7 +2796,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-05-25T13:16:28+00:00" + "time": "2018-06-25T12:29:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2928,16 +2973,16 @@ }, { "name": "symfony/process", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187" + "reference": "acc5a37c706ace827962851b69705b24e71ca17c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4cbf2db9abcb01486a21b7a059e03a62fae63187", - "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187", + "url": "https://api.github.com/repos/symfony/process/zipball/acc5a37c706ace827962851b69705b24e71ca17c", + "reference": "acc5a37c706ace827962851b69705b24e71ca17c", "shasum": "" }, "require": { @@ -2973,7 +3018,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-05-16T08:49:21+00:00" + "time": "2018-05-30T04:24:30+00:00" }, { "name": "symfony/routing", @@ -3116,16 +3161,16 @@ }, { "name": "symfony/var-dumper", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "0e6545672d8c9ce70dd472adc2f8b03155a46f73" + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e6545672d8c9ce70dd472adc2f8b03155a46f73", - "reference": "0e6545672d8c9ce70dd472adc2f8b03155a46f73", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e173954a28a44a32c690815fbe4d0f2eac43accb", + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb", "shasum": "" }, "require": { @@ -3181,11 +3226,11 @@ "debug", "dump" ], - "time": "2018-04-26T12:42:15+00:00" + "time": "2018-06-15T07:47:49+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.41", + "version": "v2.8.42", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", @@ -3344,28 +3389,28 @@ }, { "name": "vlucas/phpdotenv", - "version": "v2.4.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + "reference": "6ae3e2e6494bb5e58c2decadafc3de7f1453f70a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", - "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/6ae3e2e6494bb5e58c2decadafc3de7f1453f70a", + "reference": "6ae3e2e6494bb5e58c2decadafc3de7f1453f70a", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^4.8.35 || ^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -3375,7 +3420,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause-Attribution" + "BSD-3-Clause" ], "authors": [ { @@ -3390,7 +3435,7 @@ "env", "environment" ], - "time": "2016-09-01T10:05:43+00:00" + "time": "2018-07-01T10:25:50+00:00" }, { "name": "webmozart/assert", @@ -3442,6 +3487,50 @@ ], "time": "2018-01-29T19:49:41+00:00" }, + { + "name": "wpb/string-blade-compiler", + "version": "3.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/librenms/StringBladeCompiler.git", + "reference": "30c974a305c14f412af3a8c515b74528429c4f5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/librenms/StringBladeCompiler/zipball/30c974a305c14f412af3a8c515b74528429c4f5f", + "reference": "30c974a305c14f412af3a8c515b74528429c4f5f", + "shasum": "" + }, + "require": { + "laravel/framework": "5.4.*", + "php": ">=5.6.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Wpb\\String_Blade_Compiler\\": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Terre Porter", + "email": "tporter@webpage-builders.com" + } + ], + "description": "Laravel Blade String Compiler, render string as blade templates", + "keywords": [ + "blade", + "compiler", + "laravel" + ], + "support": { + "source": "https://github.com/librenms/StringBladeCompiler/tree/3.4" + }, + "time": "2018-06-21T21:13:41+00:00" + }, { "name": "xjtuwangke/passwordhash", "version": "dev-master", @@ -3883,51 +3972,6 @@ ], "time": "2017-01-05T08:46:19+00:00" }, - { - "name": "myclabs/deep-copy", - "version": "1.7.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2017-10-19T19:58:43+00:00" - }, { "name": "phpspec/prophecy", "version": "1.7.6", @@ -4925,7 +4969,7 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -5029,7 +5073,8 @@ "minimum-stability": "stable", "stability-flags": { "xjtuwangke/passwordhash": 20, - "oriceon/toastr-5-laravel": 20 + "oriceon/toastr-5-laravel": 20, + "wpb/string-blade-compiler": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config/app.php b/config/app.php index ed7f0ef450..1527825ce5 100644 --- a/config/app.php +++ b/config/app.php @@ -161,7 +161,7 @@ return [ Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, - Illuminate\View\ViewServiceProvider::class, + Wpb\String_Blade_Compiler\ViewServiceProvider::class, /* * Package Service Providers... @@ -182,7 +182,6 @@ return [ * Vendor Service Providers... */ Kamaln7\Toastr\ToastrServiceProvider::class, - ], /* diff --git a/doc/Alerting/Old_Templates.md b/doc/Alerting/Old_Templates.md new file mode 100644 index 0000000000..3928e15e40 --- /dev/null +++ b/doc/Alerting/Old_Templates.md @@ -0,0 +1,266 @@ +source: Alerting/Templates.md + +# Templates + +Templates can be assigned to a single or a group of rules and can contain any kind of text. There is also a default template which is used for any rule that isn't associated with a template. This template can be found under `Alert Templates` page and can be edited. It also has an option revert it back to its default content. + +The template-parser understands `if` and `foreach` controls and replaces certain placeholders with information gathered about the alert. + +## Syntax + +Controls: + +- if-else (Else can be omitted): +`{if %placeholder == value}Some Text{else}Other Text{/if}` +- foreach-loop: +`{foreach %faults}Key: %key
Value: %value{/foreach}` + +Placeholders: + +Placeholders are special variables that if used within the template will be replaced with the relevant data, I.e: + +`The device %hostname has been up for %uptime seconds` would result in the following `The device localhost has been up for 30344 seconds`. + +- Device ID: `%device_id` +- Hostname of the Device: `%hostname` +- sysName of the Device: `%sysName` +- sysDescr of the Device: `%sysDescr` +- hardware of the Device: `%hardware` +- Software version of the Device: `%version` +- location of the Device: `%location` +- uptime of the Device (in seconds): `%uptime` +- short uptime of the Device (28d 22h 30m 7s): `%uptime_short` +- long uptime of the Device (28 days, 22h 30m 7s): `%uptime_long` +- description (purpose db field) of the Device: `%description` +- notes of the Device: `%notes` +- notes of the alert: `%alert_notes` +- ping timestamp (if icmp enabled): `%ping_timestamp` +- ping loss (if icmp enabled): `%ping_loss` +- ping min (if icmp enabled): `%ping_min` +- ping max (if icmp enabled): `%ping_max` +- ping avg (if icmp enabled): `%ping_avg` +- Title for the Alert: `%title` +- Time Elapsed, Only available on recovery (`%state == 0`): `%elapsed` +- Alert-ID: `%id` +- Unique-ID: `%uid` +- Faults, Only available on alert (`%state != 0`), must be iterated in a foreach (`{foreach %faults}`). Holds all available information about the Fault, accessible in the format `%value.Column`, for example: `%value.ifDescr`. Special field `%value.string` has most Identification-information (IDs, Names, Descrs) as single string, this is the equivalent of the default used. +- State: `%state` +- Severity: `%severity` +- Rule: `%rule` +- Rule-Name: `%name` +- Timestamp: `%timestamp` +- Transport name: `%transport` + +- Contacts, must be iterated in a foreach, `%key` holds email and `%value` holds name: `%contacts` + +Placeholders can be used within the subjects for templates as well although %faults is most likely going to be worthless. + +> NOTE: Placeholder names which are contained within another need to be ordered correctly. As an example: + +```text +Limit: %value.sensor_limit / %value.sensor_limit_low +``` + +Should be done as: + +```text +Limit: %value.sensor_limit_low / %value.sensor_limit +``` + +The Default Template is a 'one-size-fit-all'. We highly recommend defining your own templates for your rules to include more specific information. + +## Examples + +Default Template: +```text +%title +Severity: %severity +{if %state == 0}Time elapsed: %elapsed{/if} +Timestamp: %timestamp +Unique-ID: %uid +Rule: {if %name}%name{else}%rule{/if} +{if %faults}Faults: +{foreach %faults} #%key: %value.string{/foreach}{/if} +Alert sent to: {foreach %contacts}%value <%key> {/foreach} +``` +Ports Utilization Template: +```text +%title +Device Name: %hostname +Severity: %severity +{if %state == 0}Time elapsed: %elapsed{/if} +Timestamp: %timestamp +Rule: {if %name}%name{else}%rule{/if} +{foreach %faults} +Physical Interface: %value.ifDescr +Interface Description: %value.ifAlias +Interface Speed: {calc (%value.ifSpeed/1000000000)} Gbs +Inbound Utilization: {calc ((%value.ifInOctets_rate*8)/%value.ifSpeed)*100}% +Outbound Utilization: {calc ((%value.ifOutOctets_rate*8)/%value.ifSpeed)*100}% +{/foreach} +``` + +Storage: +```text + +%title + +Device Name: %hostname +Severity: %severity +Uptime: %uptime_short +{if %state == 0}Time elapsed: %elapsed{/if} +Timestamp: %timestamp +Location: %location +Description: %description +Features: %features +Purpose: %purpose +Notes: %notes + +Server: %sysName {foreach %faults}Mount Point: %value.storage_descr Percent Utilized: %value.storage_perc{/foreach} +``` + +Temperature Sensors: +```text + +%title + +Device Name: %hostname +Severity: %severity +Timestamp: %timestamp +Uptime: %uptime_short +{if %state == 0}Time elapsed: %elapsed{/if} +Location: %location +Description: %description +Features: %features +Purpose: %purpose +Notes: %notes + +Rule: {if %name}%name{else}%rule{/if} +{if %faults}Faults: +{foreach %faults} +#%key: Temperature: %value.sensor_current°C +** {calc(%value.sensor_current-%value.sensor_limit)}°C over limit +Previous Measurement: %value.sensor_prev°C +High Temperature Limit: %value.sensor_limit°C +{/foreach} +{/if} +``` + +Value Sensors: +```text + +%title + +Device Name: %hostname +Severity: %severity +Timestamp: %timestamp +Uptime: %uptime_short +{if %state == 0}Time elapsed: %elapsed{/if} +Location: %location +Description: %description +Features: %features +Purpose: %purpose +Notes: %notes + +Rule: {if %name}%name{else}%rule{/if} +{if %faults}Faults: +{foreach %faults} +#%key: Sensor%value.sensor_current +** {calc(%value.sensor_current-%value.sensor_limit)}over limit +Previous Measurement: %value.sensor_prev +Limit: %value.sensor_limit +{/foreach} +{/if} +``` + +Memory Alert: +```text +%title + +Device Name: %hostname +Severity: %severity +Uptime: %uptime_short +{if %state == 0}Time elapsed: %elapsed{/if} +Timestamp: %timestamp +Location: %location +Description: %description +Notes: %notes + +Server: %hostname {foreach %faults} +Memory Description: %value.mempool_descr +Percent Utilized: %value.mempool_perc{/foreach} +``` + + +Conditional formatting example, will display a link to the host in email or just the hostname in any other transport: +```text +{if %transport == mail}%hostname +{else} +%hostname +{/if} +``` + +Note the use of double-quotes. Single quotes (`'`) in templates will be escaped (replaced with `\'`) in the output and should therefore be avoided. + +## Examples HTML + +Note: To use HTML emails you must set HTML email to Yes in the WebUI under Global Settings > Alerting Settings > Email transport > Use HTML emails + +Note: To include Graphs you must enable unauthorized graphs in config.php. Allow_unauth_graphs_cidr is optional, but more secure. +``` +$config['allow_unauth_graphs_cidr'] = array(127.0.0.1/32'); +$config['allow_unauth_graphs'] = true; +``` + +Service Alert: +``` +
+

{if %state == 1}%severity{/if} +{if %state == 2}acknowledged{/if} +{if %state == 3}recovering{/if} +{if %state == 0}recovered{/if} +

+Host: %hostname
+Duration: %elapsed
+
+ +{if %faults} +{foreach %faults}%value.service_desc - %value.service_type
+%value.service_message
+
+{/foreach} +{/if} +
+``` + +Processor Alert with Graph: +``` +%title
+Severity: %severity
+{if %state == 0}Time elapsed: %elapsed{/if} +Timestamp: %timestamp
+Alert-ID: %id
+Rule: {if %name}%name{else}%rule{/if}
+{if %faults}Faults: +{foreach %faults} +#%key: %value.string
+{/foreach} +{if %faults}Faults:
+{foreach %faults}%hostname -{else} -%hostname -{/if} +@if ($alert->transport == mail){{ $alert->hostname }} +@else +{{ $alert->hostname }} +@endif ``` -Note the use of double-quotes. Single quotes (`'`) in templates will be escaped (replaced with `\'`) in the output and should therefore be avoided. - ## Examples HTML Note: To use HTML emails you must set HTML email to Yes in the WebUI under Global Settings > Alerting Settings > Email transport > Use HTML emails @@ -215,43 +214,43 @@ $config['allow_unauth_graphs'] = true; Service Alert: ```
-

{if %state == 1}%severity{/if} -{if %state == 2}acknowledged{/if} -{if %state == 3}recovering{/if} -{if %state == 0}recovered{/if} +

@if ($alert->state == 1) {{ $alert->severity }} @endif +@if ($alert->state == 2) acknowledged @endif +@if ($alert->state == 3) recovering @endif +@if ($alert->state == 0) recovered @endif

-Host: %hostname
-Duration: %elapsed
+Host: {{ $alert->hostname }}
+Duration: {{ $alert->elapsed }}

-{if %faults} -{foreach %faults}%value.service_desc - %value.service_type
-%value.service_message
+@if ($alert->faults) +@foreach ($alert->faults as $key => $value)$value['service_desc'] - $value['service_type']
+$value['service_message']

-{/foreach} -{/if} +@endforeach +@endif

``` Processor Alert with Graph: ``` -%title
-Severity: %severity
-{if %state == 0}Time elapsed: %elapsed{/if} -Timestamp: %timestamp
-Alert-ID: %id
-Rule: {if %name}%name{else}%rule{/if}
-{if %faults}Faults: -{foreach %faults} -#%key: %value.string
-{/foreach} -{if %faults}Faults:
-{foreach %faults}
+https://server/graphs/id={{ $value['device_id'] }}/type=device_processor/
+@endforeach Template: CPU alert
-{/if} -{/if} +@endif +@endif ``` ## Included diff --git a/html/ajax_form.php b/html/ajax_form.php index 62662f5cef..8efd22ed82 100644 --- a/html/ajax_form.php +++ b/html/ajax_form.php @@ -16,10 +16,10 @@ use LibreNMS\Authentication\Auth; -$init_modules = array('web', 'auth', 'alerts'); +$init_modules = array('web', 'auth', 'alerts', 'alerts-cli'); require realpath(__DIR__ . '/..') . '/includes/init.php'; -set_debug($_REQUEST['debug']); +set_debug(isset($_REQUEST['debug']) ? $_REQUEST['debug'] : false); if (!Auth::check()) { echo 'unauthenticated'; diff --git a/html/includes/forms/alert-rules.inc.php b/html/includes/forms/alert-rules.inc.php index 06cca2a3e2..0298afa403 100644 --- a/html/includes/forms/alert-rules.inc.php +++ b/html/includes/forms/alert-rules.inc.php @@ -44,8 +44,8 @@ $rule_id = $_POST['rule_id']; $count = mres($_POST['count']); $delay = mres($_POST['delay']); $interval = mres($_POST['interval']); -$mute = mres($_POST['mute']); -$invert = mres($_POST['invert']); +$mute = mres(isset($_POST['mute']) ? $_POST['mute'] : null); +$invert = mres(isset($_POST['invert']) ? $_POST['invert'] : null); $name = mres($_POST['name']); $proc = mres($_POST['proc']); $recovery = ($vars['recovery']); @@ -138,7 +138,7 @@ if (is_numeric($rule_id) && $rule_id > 0) { if (is_numeric($rule_id) && $rule_id > 0) { $devices = []; $groups = []; - foreach ((array)$_POST['maps'] as $item) { + foreach ((array)$vars['maps'] as $item) { if (starts_with($item, 'g')) { $groups[] = (int)substr($item, 1); } else { diff --git a/html/includes/forms/alert-templates.inc.php b/html/includes/forms/alert-templates.inc.php index 2708b44ae0..b93e5745f2 100644 --- a/html/includes/forms/alert-templates.inc.php +++ b/html/includes/forms/alert-templates.inc.php @@ -24,48 +24,50 @@ use LibreNMS\Authentication\Auth; -header('Content-type: text/plain'); +$status = 'error'; if (!Auth::user()->hasGlobalAdmin()) { - die('ERROR: You need to be admin'); + header('Content-Type: application/json'); + $response = array('status' => $status, 'message' => 'You need to be admin'); + die(_json_encode($response)); } -$status = 'error'; $template_id = 0; -$name = mres($_POST['name']); -if (!empty($name)) { - if (is_numeric($_REQUEST['template_id']) && $_REQUEST['rule_id']) { +$name = mres($vars['name']); +if (isset($vars['template']) && empty(view(['template' => $vars['template']], [])->__toString())) { + $message = 'Template failed to be parsed, please check the syntax'; +} elseif (!empty($name)) { + if ((isset($vars['template_id']) && is_numeric($vars['template_id'])) && (isset($vars['rule_id']) && $vars['rule_id'])) { //Update the template/rule mapping - if (is_array($_REQUEST['rule_id'])) { - $_REQUEST['rule_id'] = implode(",", $_REQUEST['rule_id']); + if (is_array($vars['rule_id'])) { + $vars['rule_id'] = implode(",", $vars['rule_id']); } - if (substr($_REQUEST['rule_id'], 0, 1) != ",") { - $_REQUEST['rule_id'] = ",".$_REQUEST['rule_id']; + if (substr($vars['rule_id'], 0, 1) != ",") { + $vars['rule_id'] = ",".$vars['rule_id']; } - if (substr($_REQUEST['rule_id'], -1, 1) != ",") { - $_REQUEST['rule_id'] .= ","; + if (substr($vars['rule_id'], -1, 1) != ",") { + $vars['rule_id'] .= ","; } - if (dbUpdate(array('rule_id' => mres($_REQUEST['rule_id']), 'name' => $name), "alert_templates", "id = ?", array($_REQUEST['template_id'])) >= 0) { + if (dbUpdate(array('rule_id' => mres($vars['rule_id']), 'name' => $name), "alert_templates", "id = ?", array($vars['template_id'])) >= 0) { $message = "Updated template and rule id mapping"; } else { $message ="Failed to update the template and rule id mapping"; } - } elseif ($_REQUEST['template'] && is_numeric($_REQUEST['template_id'])) { + } elseif ($vars['template'] && is_numeric($vars['template_id'])) { //Update template-text - - if (dbUpdate(array('template' => $_REQUEST['template'], 'name' => $name, 'title' => $_REQUEST['title'], 'title_rec' => $_REQUEST['title_rec']), "alert_templates", "id = ?", array($_REQUEST['template_id'])) >= 0) { + if (dbUpdate(array('template' => $vars['template'], 'name' => $name, 'title' => $vars['title'], 'title_rec' => $vars['title_rec']), "alert_templates", "id = ?", array($vars['template_id'])) >= 0) { $status = 'ok'; $message = "Alert template updated"; } else { $message = "Failed to update the template"; } - } elseif ($_REQUEST['template']) { + } elseif ($vars['template']) { //Create new template if ($name != 'Default Alert Template') { - $template_id = dbInsert(array('template' => $_REQUEST['template'], 'name' => $name, 'title' => $_REQUEST['title'], 'title_rec' => $_REQUEST['title_rec']), "alert_templates"); + $template_id = dbInsert(array('template' => $vars['template'], 'name' => $name, 'title' => $vars['title'], 'title_rec' => $vars['title_rec']), "alert_templates"); if ($template_id != false) { $status = 'ok'; $message = "Alert template has been created."; @@ -84,5 +86,4 @@ if (!empty($name)) { $response = array('status' => $status, 'message' => $message, 'newid' => $template_id); -header('Content-Type: application/json'); echo _json_encode($response); diff --git a/html/includes/forms/parse-alert-template.inc.php b/html/includes/forms/parse-alert-template.inc.php index 5011c5e90f..3e28c023e0 100644 --- a/html/includes/forms/parse-alert-template.inc.php +++ b/html/includes/forms/parse-alert-template.inc.php @@ -19,7 +19,7 @@ if (!Auth::user()->hasGlobalAdmin()) { die('ERROR: You need to be admin'); } -$template_id = ($_POST['template_id']); +$template_id = ($vars['template_id']); if (is_numeric($template_id) && $template_id > 0) { $template = dbFetchRow('SELECT * FROM `alert_templates` WHERE `id` = ? LIMIT 1', array($template_id)); @@ -28,6 +28,7 @@ if (is_numeric($template_id) && $template_id > 0) { 'name' => $template['name'], 'title' => $template['title'], 'title_rec' => $template['title_rec'], + 'type' => $template['type'], ); header('Content-type: application/json'); echo _json_encode($output); diff --git a/html/includes/modal/alert_template.inc.php b/html/includes/modal/alert_template.inc.php index f1207cfa23..388941f081 100644 --- a/html/includes/modal/alert_template.inc.php +++ b/html/includes/modal/alert_template.inc.php @@ -24,73 +24,28 @@ if (!Auth::user()->hasGlobalAdmin()) {