';
-
- if ($default) {
- $output_news .= '
';
- $output_news .= '
';
- $output_news .= '
';
- $output_news .= '
';
-
- $output_news .= '
-
'.__('Welcome to our monitoring tool so grand,').'
- '.__('Where data insights are at your command.').'
- '.__('Sales, marketing, operations too,').'
- '.__("Customer support, we've got you.").'
-
-
-
'.__('Our interface is user-friendly,').'
- '.__("Customize your dashboard, it's easy.").'
- '.__('Set up alerts and gain insights so keen,').'
- '.__("Optimize your data, like you've never seen.").'
-
-
-
'.__('Unleash its power now, and join the pro league,').'
- '.__('Unlock the potential of your data to intrigue.').'
- '.__('Monitoring made simple, efficient and fun,').'
- '.__('Discover a whole new way to get things done.').'
-
-
-
'.__('And take control of your IT once and for all.').'
-
-
'.__('You can replace this message with a personalized one at Admin tools -> Site news.').'
- ';
-
- $output_news .= '
';
- } else {
- $text = str_replace('';
+ return $js;
+ }
+
+
+ /**
+ * Return the welcome message.
+ *
+ * @return string
+ */
+ private function getWelcomeMessage():string
+ {
+ global $config;
+ $user = users_get_user_by_id($config['id_user']);
+ if (is_array($user) === true && count($user) > 0) {
+ $name = $user['fullname'];
+ } else {
+ $name = '';
+ }
+
+ if (empty($name) === true) {
+ $message = __('Welcome back! 👋');
+ } else {
+ $message = __('Welcome back %s! 👋', $name);
+ }
+
+ return html_print_div(
+ [
+ 'content' => $message,
+ 'class' => 'message-welcome',
+ ],
+ true
+ );
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Agents.php b/pandora_console/include/lib/TacticalView/elements/Agents.php
new file mode 100644
index 0000000000..97063ec300
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Agents.php
@@ -0,0 +1,446 @@
+title = __('Agents');
+ $this->ajaxMethods = ['getGroups'];
+ }
+
+
+ /**
+ * Get total number of agents.
+ *
+ * @return string
+ */
+ public function getTotalAgents():string
+ {
+ $agents = agents_get_agents();
+ if (is_array($agents) === true) {
+ $total = count($agents);
+ } else {
+ $total = 0;
+ }
+
+ return html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Get total alerts of agents.
+ *
+ * @return string
+ */
+ public function getAlerts():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $group_query = ' AND (
+ t3.id_grupo IN ('.$id_groups.')
+ OR tasg.id_group IN ('.$id_groups.')
+ )';
+ $sql = 'SELECT count(t0.id)
+ FROM talert_template_modules t0
+ INNER JOIN talert_templates t1
+ ON t0.id_alert_template = t1.id
+ INNER JOIN tagente_modulo t2
+ ON t0.id_agent_module = t2.id_agente_modulo
+ INNER JOIN tagente t3
+ ON t2.id_agente = t3.id_agente
+ LEFT JOIN tagent_secondary_group tasg
+ ON tasg.id_agent = t3.id_agente
+ WHERE last_fired >=UNIX_TIMESTAMP(NOW() - INTERVAL 1 DAY) '.$group_query;
+
+ $total = db_get_value_sql($sql);
+ return html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Get a datatable with the top groups with more agents.
+ *
+ * @return string
+ */
+ public function getDataTableGroups():string
+ {
+ $columns = [
+ 'nombre',
+ 'total',
+ ];
+
+ $columnNames = [
+ __('Group alias'),
+ __('Agents'),
+ ];
+
+ return ui_print_datatable(
+ [
+ 'id' => 'list_groups',
+ 'class' => 'info_table',
+ 'style' => 'width: 90%',
+ 'dom_elements' => 'tfp',
+ 'filter_main_class' => 'box-flat white_table_graph fixed_filter_bar',
+ 'columns' => $columns,
+ 'column_names' => $columnNames,
+ 'ajax_url' => $this->ajaxController,
+ 'no_sortable_columns' => [
+ 0,
+ 1,
+ ],
+ 'ajax_data' => [
+ 'method' => 'getGroups',
+ 'class' => static::class,
+ ],
+ 'order' => [
+ 'field' => 'title',
+ 'direction' => 'asc',
+ ],
+ 'default_pagination' => 8,
+ 'search_button_class' => 'sub filter float-right',
+ 'return' => true,
+ ]
+ );
+ }
+
+
+ /**
+ * Return top 20 groups with more agents for ajax datatable.
+ *
+ * @return string
+ */
+ public function getGroups():string
+ {
+ global $config;
+
+ $start = get_parameter('start', 0);
+ $length = get_parameter('length', $config['block_size']);
+ $pagination = '';
+
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ try {
+ ob_start();
+
+ if (isset($length) && $length > 0
+ && isset($start) && $start >= 0
+ ) {
+ $pagination = sprintf(
+ ' LIMIT %d OFFSET %d ',
+ $length,
+ $start
+ );
+ }
+
+ $sql = sprintf(
+ 'SELECT gr.nombre, count(*) +
+ IFNULL((SELECT count(*) AS total
+ FROM tagente second_a
+ LEFT JOIN tagent_secondary_group second_g ON second_g.id_agent = second_a.id_agente
+ WHERE a.id_grupo = second_g.id_group
+ GROUP BY second_g.id_group
+ ), 0) AS total
+ FROM tagente a
+ LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ INNER JOIN(
+ SELECT gr.id_grupo, count(*) AS total
+ FROM tagente a LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ WHERE a.id_grupo IN ('.$id_groups.') OR g.id_group IN ('.$id_groups.')
+ GROUP BY a.id_grupo ORDER BY total DESC LIMIT 20
+ ) top_groups ON top_groups.id_grupo = gr.id_grupo
+ WHERE a.id_grupo IN ('.$id_groups.') OR g.id_group IN ('.$id_groups.')
+ GROUP BY a.id_grupo
+ ORDER BY total DESC
+ %s',
+ $pagination
+ );
+
+ $rows = db_process_sql($sql);
+
+ $sql_count = 'SELECT gr.nombre,
+ IFNULL((SELECT count(*) AS total
+ FROM tagente second_a
+ LEFT JOIN tagent_secondary_group second_g ON second_g.id_agent = second_a.id_agente
+ WHERE a.id_grupo = second_g.id_group
+ GROUP BY second_g.id_group
+ ), 0) AS total
+ FROM tagente a
+ LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ INNER JOIN(
+ SELECT gr.id_grupo, count(*) AS total
+ FROM tagente a LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ WHERE a.id_grupo IN ('.$id_groups.') OR g.id_group IN ('.$id_groups.')
+ GROUP BY a.id_grupo ORDER BY total DESC LIMIT 20
+ ) top_groups ON top_groups.id_grupo = gr.id_grupo
+ WHERE a.id_grupo IN ('.$id_groups.') OR g.id_group IN ('.$id_groups.')
+ GROUP BY a.id_grupo
+ ORDER BY total DESC';
+
+ $total = db_get_num_rows($sql_count);
+
+ // Capture output.
+ $response = ob_get_clean();
+
+ return json_encode(
+ [
+ 'data' => $rows,
+ 'recordsTotal' => $total,
+ 'recordsFiltered' => $total,
+ ]
+ );
+ } catch (Exception $e) {
+ return json_encode(['error' => $e->getMessage()]);
+ }
+
+ return json_decode($response);
+ if (json_last_error() === JSON_ERROR_NONE) {
+ return $response;
+ } else {
+ return json_encode(
+ [
+ 'success' => false,
+ 'error' => $response,
+ ]
+ );
+ }
+ }
+
+
+ /**
+ * Return the html graph of number agents by os.
+ *
+ * @return string
+ */
+ public function getOperatingSystemGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $sql = 'SELECT name, count(*) AS total
+ FROM tagente a
+ LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ LEFT JOIN tconfig_os os ON os.id_os = a.id_os
+ WHERE a.id_grupo IN ('.$id_groups.') OR g.id_group IN ('.$id_groups.')
+ GROUP BY a.id_os
+ ORDER BY total DESC';
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ foreach ($rows as $key => $row) {
+ if (empty($row['name']) === true) {
+ continue;
+ }
+
+ $labels[] = $this->controlSizeText($row['name']);
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => [
+ 'position' => 'bottom',
+ 'align' => 'right',
+ 'display' => false,
+ ],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Return the html graph of number agents by status.
+ *
+ * @return string
+ */
+ public function getStatusGraph():string
+ {
+ $agents = agents_get_agents(
+ false,
+ [
+ 'id_agente',
+ 'id_grupo',
+ 'nombre',
+ 'alias',
+ 'id_os',
+ 'ultimo_contacto',
+ 'intervalo',
+ 'comentarios description',
+ 'quiet',
+ 'normal_count',
+ 'warning_count',
+ 'critical_count',
+ 'unknown_count',
+ 'notinit_count',
+ 'total_count',
+ 'fired_count',
+ 'ultimo_contacto_remoto',
+ 'remote',
+ 'agent_version',
+ ]
+ );
+ $labels = [
+ __('No Monitors'),
+ __('CRITICAL'),
+ __('WARNING'),
+ __('UKNOWN'),
+ __('NORMAL'),
+ ];
+ $totals = [
+ 'no_monitors' => 0,
+ 'critical' => 0,
+ 'warning' => 0,
+ 'unknown' => 0,
+ 'ok' => 0,
+ ];
+
+ $colors = [
+ COL_NOTINIT,
+ COL_CRITICAL,
+ COL_WARNING,
+ COL_UNKNOWN,
+ COL_NORMAL,
+ ];
+
+ foreach ($agents as $key => $agent) {
+ if ($agent['total_count'] == 0 || $agent['total_count'] == $agent['notinit_count']) {
+ $totals['no_monitors']++;
+ }
+
+ if ($agent['critical_count'] > 0) {
+ $totals['critical']++;
+ } else if ($agent['warning_count'] > 0) {
+ $totals['warning']++;
+ } else if ($agent['unknown_count'] > 0) {
+ $totals['unknown']++;
+ } else {
+ $totals['ok']++;
+ }
+ }
+
+ foreach ($totals as $key => $total) {
+ $data[] = $total;
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => [
+ 'position' => 'bottom',
+ 'align' => 'right',
+ 'display' => false,
+ ],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '80%'],
+ 'colors' => $colors,
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Alerts.php b/pandora_console/include/lib/TacticalView/elements/Alerts.php
new file mode 100644
index 0000000000..1c4388e708
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Alerts.php
@@ -0,0 +1,274 @@
+title = __('Alerts');
+ $this->ajaxMethods = ['getUsers'];
+ $this->ajaxMethods = [
+ 'getUsers',
+ 'getCurrentlyTriggered',
+ 'getActiveAlerts',
+ ];
+ $this->interval = 300000;
+ $this->refreshConfig = [
+ 'triggered' => [
+ 'id' => 'currently-triggered',
+ 'method' => 'getCurrentlyTriggered',
+ ],
+ 'active-correlation' => [
+ 'id' => 'active-correlation',
+ 'method' => 'getActiveAlerts',
+ ],
+ ];
+ }
+
+
+ /**
+ * Returns the html of currently triggered.
+ *
+ * @return string
+ */
+ public function getCurrentlyTriggered():string
+ {
+ $total = alerts_get_alerts(0, '', 'fired', -1, 'AR', true);
+ return html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l',
+ 'id' => 'currently-triggered',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of active correlation.
+ *
+ * @return string
+ */
+ public function getActiveAlerts():string
+ {
+ $total = alerts_get_alerts(0, '', 'all', -1, 'AR', true);
+ return html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l',
+ 'id' => 'active-correlation',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Return a datatable with de users lists.
+ *
+ * @return string
+ */
+ public function getDataTableUsers():string
+ {
+ $columns = [
+ 'id_user',
+ 'is_admin',
+ 'last_connect',
+ ];
+
+ $columnNames = [
+ __('User'),
+ __('Role'),
+ __('Last seen'),
+ ];
+
+ return ui_print_datatable(
+ [
+ 'id' => 'list_users',
+ 'class' => 'info_table',
+ 'style' => 'width: 90%',
+ 'dom_elements' => 'tfp',
+ 'filter_main_class' => 'box-flat white_table_graph fixed_filter_bar',
+ 'columns' => $columns,
+ 'column_names' => $columnNames,
+ 'ajax_url' => $this->ajaxController,
+ 'ajax_data' => [
+ 'method' => 'getUsers',
+ 'class' => static::class,
+ ],
+ 'order' => [
+ 'field' => 'title',
+ 'direction' => 'asc',
+ ],
+ 'default_pagination' => 10,
+ 'search_button_class' => 'sub filter float-right',
+ 'return' => true,
+ ]
+ );
+ }
+
+
+ /**
+ * Return all users for ajax.
+ *
+ * @return string
+ */
+ public function getUsers():string
+ {
+ global $config;
+
+ $start = get_parameter('start', 0);
+ $length = get_parameter('length', $config['block_size']);
+ $orderDatatable = get_datatable_order(true);
+ $pagination = '';
+ $order = '';
+
+ try {
+ ob_start();
+ if (isset($orderDatatable)) {
+ $order = sprintf(
+ ' ORDER BY %s %s',
+ $orderDatatable['field'],
+ $orderDatatable['direction']
+ );
+ }
+
+ if (isset($length) && $length > 0
+ && isset($start) && $start >= 0
+ ) {
+ $pagination = sprintf(
+ ' LIMIT %d OFFSET %d ',
+ $length,
+ $start
+ );
+ }
+
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $sql = sprintf(
+ 'SELECT DISTINCT id_user, is_admin ,last_connect
+ FROM tusuario u
+ LEFT JOIN tusuario_perfil p ON p.id_usuario = u.id_user
+ WHERE id_grupo IN ('.$id_groups.')
+ GROUP BY id_user
+ %s %s',
+ $order,
+ $pagination
+ );
+
+ $rows = db_process_sql($sql);
+
+ foreach ($rows as $key => $row) {
+ $rows[$key]['id_user'] = '
'.$row['id_user'].' ';
+ if ((bool) $row['is_admin'] === true) {
+ $rows[$key]['is_admin'] = '
'.__('Admin').' ';
+ } else {
+ $rows[$key]['is_admin'] = '
'.__('User').' ';
+ }
+
+ if ($row['last_connect'] > 0) {
+ $rows[$key]['last_connect'] = ui_print_timestamp($row['last_connect'], true, ['prominent' => 'compact']);
+ } else {
+ $rows[$key]['last_connect'] = __('Unknown');
+ }
+ }
+
+ $sql_count = sprintf(
+ 'SELECT DISTINCT id_user, count(*) as total
+ FROM tusuario u
+ LEFT JOIN tusuario_perfil p ON p.id_usuario = u.id_user
+ WHERE id_grupo IN ('.$id_groups.')
+ %s',
+ $order,
+ );
+
+ $total = db_process_sql($sql_count);
+
+ // Capture output.
+ $response = ob_get_clean();
+
+ return json_encode(
+ [
+ 'data' => $rows,
+ 'recordsTotal' => $total[0]['total'],
+ 'recordsFiltered' => $total[0]['total'],
+ ]
+ );
+ } catch (Exception $e) {
+ return json_encode(['error' => $e->getMessage()]);
+ }
+
+ json_decode($response);
+ if (json_last_error() === JSON_ERROR_NONE) {
+ return $response;
+ } else {
+ return json_encode(
+ [
+ 'success' => false,
+ 'error' => $response,
+ ]
+ );
+ }
+ }
+
+
+ /**
+ * Check if user can manager users.
+ *
+ * @return boolean
+ */
+ public function checkAclUserList():bool
+ {
+ global $config;
+ $user_m = (bool) check_acl($config['id_user'], 0, 'UM');
+ return $user_m;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Configurations.php b/pandora_console/include/lib/TacticalView/elements/Configurations.php
new file mode 100644
index 0000000000..3fb4f5bec3
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Configurations.php
@@ -0,0 +1,252 @@
+title = __('Configurations');
+ }
+
+
+ /**
+ * Get total groups from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalGroups():string
+ {
+ $value = $this->valueMonitoring('total_groups');
+ $total = round($value[0]['datos']);
+ $image = html_print_image('images/Tactical_Groups.svg', true);
+ $text = '
'.__('Groups').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total modules from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalModules():string
+ {
+ $value = $this->valueMonitoring('total_modules');
+ $total = round($value[0]['datos']);
+ $image = html_print_image('images/Tactical_Modules.svg', true);
+ $text = '
'.__('Modules').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total policies from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalPolicies():string
+ {
+ $totalPolicies = db_get_value(
+ 'count(*)',
+ 'tpolicies'
+ );
+
+ $image = html_print_image('images/Tactical_Policies.svg', true);
+ $text = '
'.__('Policies').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($totalPolicies, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total remote plugins from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalRemotePlugins():string
+ {
+ $totalPLugins = db_get_value(
+ 'count(*)',
+ 'tplugin',
+ 'plugin_type',
+ 1,
+ );
+
+ $sql = 'SELECT count(*) AS total FROM tplugin WHERE plugin_type = 1;';
+ $rows = db_process_sql($sql);
+ $totalPLugins = 0;
+ if (is_array($rows) === true && count($rows) > 0) {
+ $totalPLugins = $rows[0]['total'];
+ }
+
+ $image = html_print_image('images/Tactical_Plugins.svg', true);
+ $text = '
'.__('Remote plugins').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($totalPLugins, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total module templates from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalModuleTemplate():string
+ {
+ $countModuleTemplates = db_get_value(
+ 'count(*)',
+ 'tnetwork_profile'
+ );
+
+ $image = html_print_image('images/Tactical_Module_template.svg', true);
+ $text = '
'.__('Module templates').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($countModuleTemplates, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total not unit modules from automonitorization.
+ *
+ * @return string
+ */
+ public function getNotInitModules():string
+ {
+ $value = $this->valueMonitoring('total_notinit');
+ $total = round($value[0]['datos']);
+ $image = html_print_image('images/Tactical_Not_init_module.svg', true);
+ $text = '
'.__('Not-init modules').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Get total unknow agents from automonitorization.
+ *
+ * @return string
+ */
+ public function getTotalUnknowAgents():string
+ {
+ $value = $this->valueMonitoring('total_unknown');
+ $total = round($value[0]['datos']);
+ $image = html_print_image('images/Tactical_Unknown_agent.svg', true);
+ $text = '
'.__('Unknown agents').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+ /**
+ * Returns the html of total events.
+ *
+ * @return string
+ */
+ public function getTotalEvents():string
+ {
+ $data = $this->valueMonitoring('last_events_24h');
+ $total = $data[0]['datos'];
+ $image = html_print_image('images/system_event.svg', true);
+ $text = '
'.__('Events in last 24 hrs').' ';
+ $number = html_print_div(
+ [
+ 'content' => format_numeric($total, 0),
+ 'class' => 'text-l text_center',
+ 'style' => '',
+ ],
+ true
+ );
+ $output = $image.$text.$number;
+ return $output;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Database.php b/pandora_console/include/lib/TacticalView/elements/Database.php
new file mode 100644
index 0000000000..21f8053163
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Database.php
@@ -0,0 +1,348 @@
+title = __('Database');
+ $this->ajaxMethods = [
+ 'getStatus',
+ 'getDataRecords',
+ 'getEvents',
+ 'getStringRecords',
+ 'getReadsGraph',
+ 'getWritesGraph',
+ ];
+ $this->interval = 300000;
+ $this->refreshConfig = [
+ 'status' => [
+ 'id' => 'status-database',
+ 'method' => 'getStatus',
+ ],
+ 'records' => [
+ 'id' => 'data-records',
+ 'method' => 'getDataRecords',
+ ],
+ 'events' => [
+ 'id' => 'total-events',
+ 'method' => 'getEvents',
+ ],
+ 'totalRecords' => [
+ 'id' => 'total-records',
+ 'method' => 'getStringRecords',
+
+ ],
+ 'reads' => [
+ 'id' => 'database-reads',
+ 'method' => 'getReadsGraph',
+ ],
+ 'writes' => [
+ 'id' => 'database-writes',
+ 'method' => 'getWritesGraph',
+ ],
+ ];
+ }
+
+
+ /**
+ * Returns the html status of database.
+ *
+ * @return string
+ */
+ public function getStatus():string
+ {
+ // TODO connect to automonitorization.
+ $status = true;
+
+ if ($status === true) {
+ $image_status = html_print_image('images/status_check@svg.svg', true);
+ $text = html_print_div(
+ [
+ 'content' => __('Everything’s OK!'),
+ 'class' => 'status-text',
+ ],
+ true
+ );
+ } else {
+ $image_status = html_print_image('images/status_error@svg.svg', true);
+ $text = html_print_div(
+ [
+ 'content' => __('Something’s wrong'),
+ 'class' => 'status-text',
+ ],
+ true
+ );
+ }
+
+ $output = $image_status.$text;
+
+ return html_print_div(
+ [
+ 'content' => $output,
+ 'class' => 'flex_center margin-top-5',
+ 'id' => 'status-database',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html records data of database.
+ *
+ * @return string
+ */
+ public function getDataRecords():string
+ {
+ $data = $this->valueMonitoring('mysql_size_of_data');
+ $value = format_numeric($data[0]['datos'], 2).' MB';
+ return html_print_div(
+ [
+ 'content' => $value,
+ 'class' => 'text-l',
+ 'id' => 'data-records',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of total events.
+ *
+ * @return string
+ */
+ public function getEvents():string
+ {
+ $data = $this->valueMonitoring('last_events_24h');
+ $value = format_numeric($data[0]['datos']);
+ return html_print_div(
+ [
+ 'content' => $value,
+ 'class' => 'text-l',
+ 'id' => 'total-events',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of total records.
+ *
+ * @return string
+ */
+ public function getStringRecords():string
+ {
+ $data = $this->valueMonitoring('total_string_data');
+ $value = format_numeric($data[0]['datos']);
+ return html_print_div(
+ [
+ 'content' => $value,
+ 'class' => 'text-l',
+ 'id' => 'total-records',
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of total reads database in a graph.
+ *
+ * @return string
+ */
+ public function getReadsGraph():string
+ {
+ $dateInit = (time() - 86400);
+ $reads = $this->valueMonitoring('mysql_questions_reads', $dateInit, time());
+ $dates = [];
+ $string_reads = [];
+ $total = 0;
+ foreach ($reads as $key => $read) {
+ $dates[] = date('d-m-Y H:i:s', $read['utimestamp']);
+ $string_reads[] = $read['datos'];
+ $total += $read['datos'];
+ }
+
+ $options = [
+ 'labels' => $dates,
+ 'legend' => [ 'display' => false ],
+ 'tooltips' => [ 'display' => false ],
+ 'scales' => [
+ 'y' => [
+ 'grid' => ['display' => false],
+ 'ticks' => ['display' => false],
+ 'display' => false,
+ ],
+ 'x' => [
+ 'grid' => ['display' => false],
+ 'display' => false,
+ ],
+ ],
+ 'elements' => [ 'point' => [ 'radius' => 0 ] ],
+ ];
+
+ $data = [
+ [
+ 'backgroundColor' => '#EC7176',
+ 'borderColor' => '#EC7176',
+ 'pointBackgroundColor' => '#EC7176',
+ 'pointHoverBorderColor' => '#EC7176',
+ 'data' => $string_reads,
+ ],
+ ];
+
+ $graph_area = html_print_div(
+ [
+ 'content' => line_graph($data, $options),
+ 'class' => 'w100p h100p centered',
+ 'style' => 'max-height: 83px; max-width: 93%; margin-bottom: 10px;',
+ ],
+ true
+ );
+
+ $total = html_print_div(
+ [
+ 'content' => format_numeric($total),
+ 'class' => 'text-xl',
+ ],
+ true
+ );
+
+ $output = html_print_div(
+ [
+ 'content' => $total.$graph_area,
+ 'id' => 'database-reads',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Returns the html of total writes database in a graph.
+ *
+ * @return string
+ */
+ public function getWritesGraph():string
+ {
+ $dateInit = (time() - 86400);
+ $writes = $this->valueMonitoring('mysql_questions_writes', $dateInit, time());
+ $dates = [];
+ $string_writes = [];
+ $total = 0;
+ foreach ($writes as $key => $write) {
+ $dates[] = date('d-m-Y H:i:s', $write['utimestamp']);
+ $string_writes[] = $write['datos'];
+ $total += $write['datos'];
+ }
+
+ $options = [
+ 'labels' => $dates,
+ 'legend' => [ 'display' => false ],
+ 'tooltips' => [ 'display' => false ],
+ 'scales' => [
+ 'y' => [
+ 'grid' => ['display' => false],
+ 'ticks' => ['display' => false],
+ 'display' => false,
+ ],
+ 'x' => [
+ 'grid' => ['display' => false],
+ 'display' => false,
+ ],
+ ],
+ 'elements' => [ 'point' => [ 'radius' => 0 ] ],
+ ];
+
+ $data = [
+ [
+ 'backgroundColor' => '#009D9E',
+ 'borderColor' => '#009D9E',
+ 'pointBackgroundColor' => '#009D9E',
+ 'pointHoverBorderColor' => '#009D9E',
+ 'data' => $string_writes,
+ ],
+ ];
+
+ $graph_area = html_print_div(
+ [
+ 'content' => line_graph($data, $options),
+ 'class' => 'w100p h100p centered',
+ 'style' => 'max-height: 83px; max-width: 93%; margin-bottom: 10px;',
+ ],
+ true
+ );
+
+ $total = html_print_div(
+ [
+ 'content' => format_numeric($total),
+ 'class' => 'text-xl',
+ ],
+ true
+ );
+
+ $output = html_print_div(
+ [
+ 'content' => $total.$graph_area,
+ 'id' => 'database-writes',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Check if user can manage database
+ *
+ * @return boolean
+ */
+ public function checkAcl():bool
+ {
+ global $config;
+ $db_m = (bool) check_acl($config['id_user'], 0, 'DM');
+ return $db_m;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Events.php b/pandora_console/include/lib/TacticalView/elements/Events.php
new file mode 100644
index 0000000000..a7f9970ee3
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Events.php
@@ -0,0 +1,485 @@
+title = __('Events');
+ $this->ajaxMethods = [
+ 'getEventsGraph',
+ 'getEventsCriticalityGraph',
+ 'getEventsStatusValidateGraph',
+ 'getEventsStatusGraph',
+ ];
+ }
+
+
+ /**
+ * Return the html graph of events in last 24h.
+ *
+ * @return string
+ */
+ public function getEventsGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+ $event_view_h = (int) ($config['event_view_hr'] > 24) ? 24 : $config['event_view_hr'];
+ $time_events = ($event_view_h * 3600);
+ $intervalh = (time() - $time_events);
+ $sql = 'SELECT utimestamp from tevento WHERE utimestamp >= '.$intervalh.' ORDER BY utimestamp DESC;';
+ $rows = db_process_sql($sql);
+ $cut_seconds = ($time_events / 24);
+ $now = (time() - 300);
+ $cuts_intervals = [];
+ for ($i = 0; $i < 24; $i++) {
+ $cuts_intervals[$now] = 0;
+ $now -= $cut_seconds;
+ }
+
+ foreach ($rows as $key => $row) {
+ foreach ($cuts_intervals as $time => $count) {
+ if ($row['utimestamp'] > $time) {
+ $cuts_intervals[$time]++;
+ break;
+ }
+ }
+ }
+
+ $cuts_intervals = array_reverse($cuts_intervals, true);
+ $graph_values = [];
+ $colors = [];
+ $max_value = 0;
+ foreach ($cuts_intervals as $utimestamp => $count) {
+ if ($max_value < $count) {
+ $max_value = $count;
+ }
+
+ $graph_values[] = [
+ 'y' => $count,
+ 'x' => date('d-m-Y H:i:s', $utimestamp),
+ ];
+ }
+
+ $danger = $max_value;
+ $ok = ($max_value / 3);
+
+ foreach ($graph_values as $key => $value) {
+ if ($value['y'] >= $danger) {
+ $colors[] = '#EC7176';
+ }
+
+ if ($value['y'] >= $ok && $value['y'] < $danger) {
+ $colors[] = '#FCAB10';
+ }
+
+ if ($value['y'] < $ok) {
+ $colors[] = '#82B92E';
+ }
+ }
+
+ $options = [
+ 'height' => 237,
+ 'legend' => ['display' => false],
+ 'scales' => [
+ 'x' => [
+ 'bounds' => 'data',
+ 'grid' => ['display' => false],
+ 'display' => false,
+ ],
+ 'y' => [
+ 'grid' => ['display' => false],
+ ],
+ ],
+ 'colors' => $colors,
+ 'borderColors' => ['#ffffff'],
+ ];
+
+ $bar = vbar_graph($graph_values, $options);
+
+ $output = html_print_div(
+ [
+ 'content' => $bar,
+ 'class' => 'margin-top-5 w100p relative',
+ 'style' => 'max-height: 250px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Return the html graph of events in last 8h grouped by criticity.
+ *
+ * @return string
+ */
+ public function getEventsCriticalityGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+ $event_view_h = (int) ($config['event_view_hr'] > 24) ? 24 : $config['event_view_hr'];
+ $time_events = ($event_view_h * 3600);
+ $intervalh = (time() - $time_events);
+ $sql = 'SELECT criticity, count(*) AS total
+ FROM tevento
+ WHERE utimestamp >= '.$intervalh.' AND id_grupo IN ('.$id_groups.')
+ group by criticity';
+
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ $colors = [];
+ foreach ($rows as $key => $row) {
+ switch ($row['criticity']) {
+ case EVENT_CRIT_CRITICAL:
+ $label = __('CRITICAL');
+ $colors[] = COL_CRITICAL;
+ break;
+
+ case EVENT_CRIT_MAINTENANCE:
+ $label = __('MAINTENANCE');
+ $colors[] = COL_MAINTENANCE;
+ break;
+
+ case EVENT_CRIT_INFORMATIONAL:
+ $label = __('INFORMATIONAL');
+ $colors[] = COL_INFORMATIONAL;
+ break;
+
+ case EVENT_CRIT_MAJOR:
+ $label = __('MAJOR');
+ $colors[] = COL_MAJOR;
+ break;
+
+ case EVENT_CRIT_MINOR:
+ $label = __('MINOR');
+ $colors[] = COL_MINOR;
+ break;
+
+ case EVENT_CRIT_NORMAL:
+ $label = __('NORMAL');
+ $colors[] = COL_NORMAL;
+ break;
+
+ case EVENT_CRIT_WARNING:
+ $label = __('WARNING');
+ $colors[] = COL_WARNING;
+ break;
+
+ default:
+ $colors[] = COL_UNKNOWN;
+ $label = __('UNKNOWN');
+ break;
+ }
+
+ $labels[] = $this->controlSizeText($label);
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'waterMark' => false,
+ 'labels' => $labels,
+ 'legend' => ['display' => false],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ 'colors' => $colors,
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Return the html graph of events in last 8h grouped by status validate.
+ *
+ * @return string
+ */
+ public function getEventsStatusValidateGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+ $event_view_h = (int) ($config['event_view_hr'] > 24) ? 24 : $config['event_view_hr'];
+ $time_events = ($event_view_h * 3600);
+ $intervalh = (time() - $time_events);
+ $sql = 'SELECT estado, count(*) AS total
+ FROM tevento
+ WHERE utimestamp >= '.$intervalh.' AND id_grupo IN ('.$id_groups.')
+ group by estado';
+
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ foreach ($rows as $key => $row) {
+ switch ($row['estado']) {
+ case '2':
+ $label = _('In process');
+ break;
+
+ case '0':
+ $label = _('New events');
+ break;
+
+ case '3':
+ $label = _('Not validated');
+ break;
+
+ case '1':
+ $label = _('Validated events');
+ break;
+
+ default:
+ $label = __('Unknow');
+ break;
+ }
+
+ $labels[] = $label;
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'waterMark' => false,
+ 'labels' => $labels,
+ 'legend' => ['display' => false],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ ];
+
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Return the html graph of events in last 8h grouped by status.
+ *
+ * @return string
+ */
+ public function getEventsStatusGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ if (users_can_manage_group_all() === true) {
+ $id_groups[] = 0;
+ }
+
+ $id_groups = implode(',', $id_groups);
+ $event_view_h = (int) ($config['event_view_hr'] > 24) ? 24 : $config['event_view_hr'];
+ $time_events = ($event_view_h * 3600);
+ $intervalh = (time() - $time_events);
+ $sql = 'SELECT criticity, count(*) AS total
+ FROM tevento
+ WHERE utimestamp >= '.$intervalh.' AND id_grupo IN ('.$id_groups.')
+ group by criticity';
+
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ $colors = [];
+ foreach ($rows as $key => $row) {
+ switch ($row['criticity']) {
+ case EVENT_CRIT_CRITICAL:
+ $label = __('CRITICAL');
+ $colors[] = COL_CRITICAL;
+ break;
+
+ case EVENT_CRIT_NORMAL:
+ $label = __('NORMAL');
+ $colors[] = COL_NORMAL;
+ break;
+
+ case EVENT_CRIT_WARNING:
+ $label = __('WARNING');
+ $colors[] = COL_WARNING;
+ break;
+
+ default:
+ $colors[] = COL_UNKNOWN;
+ $label = __('UNKNOWN');
+ break;
+ }
+
+ $labels[] = $this->controlSizeText($label);
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => ['display' => false],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ 'colors' => $colors,
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Return the datatable events in last 8 hours.
+ *
+ * @return string
+ */
+ public function getDataTableEvents()
+ {
+ $column_names = [
+ __('S'),
+ __('Event'),
+ __('Date'),
+ ];
+
+ $fields = [
+ 'mini_severity',
+ 'evento',
+ 'timestamp',
+ ];
+ return ui_print_datatable(
+ [
+ 'id' => 'datatable_events',
+ 'class' => 'info_table events',
+ 'style' => 'width: 90%;',
+ 'ajax_url' => 'operation/events/events',
+ 'ajax_data' => [
+ 'get_events' => 1,
+ 'compact_date' => 1,
+ 'external_url' => 1,
+ ],
+ 'order' => [
+ 'field' => 'timestamp',
+ 'direction' => 'desc',
+ ],
+ 'column_names' => $column_names,
+ 'columns' => $fields,
+ 'ajax_return_operation' => 'buffers',
+ 'ajax_return_operation_function' => 'process_buffers',
+ 'return' => true,
+ 'csv' => 0,
+ 'dom_elements' => 'tfp',
+ 'default_pagination' => 8,
+ ]
+ );
+ }
+
+
+ /**
+ * Check permission user for view events section.
+ *
+ * @return boolean
+ */
+ public function checkAcl():bool
+ {
+ global $config;
+ $event_a = (bool) check_acl($config['id_user'], 0, 'ER');
+ return $event_a;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/Groups.php b/pandora_console/include/lib/TacticalView/elements/Groups.php
new file mode 100644
index 0000000000..82b0f358b1
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/Groups.php
@@ -0,0 +1,563 @@
+ajaxMethods = ['getStatusHeatMap'];
+ ui_require_css_file('heatmap');
+ $this->title = __('Groups');
+ $this->total = $this->calculateTotalGroups();
+ }
+
+
+ /**
+ * Return the total groups.
+ *
+ * @return integer
+ */
+ public function calculateTotalGroups():int
+ {
+ $total = db_get_value_sql('SELECT count(*) FROM tgrupo');
+ return $total;
+ }
+
+
+ /**
+ * Return the status groups in heat map.
+ *
+ * @return string
+ */
+ public function getStatusHeatMap():string
+ {
+ global $config;
+
+ $groups = users_get_groups($config['id_group'], 'AR', false);
+ if (is_array($groups) === true && count($groups) >= 10) {
+ return $this->getStatusHeatMapGroup();
+ }
+
+ $agents = agents_get_agents();
+ if (is_array($agents) === true && count($agents) >= 10) {
+ $this->title = __('My monitored agents');
+ return $this->getStatusHeatMapAgents().'
'.$this->title.' ';
+ }
+
+ $this->title = __('My monitored modules');
+ return $this->getStatusHeatMapModules().'
'.$this->title.' ';
+ }
+
+
+ /**
+ * Return the status modules in heatmap.
+ *
+ * @return string
+ */
+ public function getStatusHeatMapModules():string
+ {
+ global $config;
+ $width = get_parameter('width', 350);
+ $height = get_parameter('height', 275);
+
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $modules = modules_get_modules_in_group($id_groups);
+ $total_groups = count($modules);
+ if ($total_groups === 0) {
+ return graph_nodata_image(['width' => '400']);
+ }
+
+ $groups = $modules;
+ // Best square.
+ $high = (float) max($width, $height);
+ $low = 0.0;
+
+ while (abs($high - $low) > 0.000001) {
+ $mid = (($high + $low) / 2.0);
+ $midval = (floor($width / $mid) * floor($height / $mid));
+ if ($midval >= $total_groups) {
+ $low = $mid;
+ } else {
+ $high = $mid;
+ }
+ }
+
+ $square_length = min(($width / floor($width / $low)), ($height / floor($height / $low)));
+ // Print starmap.
+ $heatmap = sprintf(
+ '
',
+ $width,
+ $height
+ );
+
+ $heatmap .= '';
+ $row = 0;
+ $column = 0;
+ $x = 0;
+ $y = 0;
+ $cont = 1;
+ foreach ($groups as $key => $value) {
+ $module_id = $value['id_agente_modulo'];
+ $db_status = modules_get_agentmodule_status($module_id);
+ $module_value = modules_get_last_value($module_id);
+ $status = '';
+ $title = '';
+ modules_get_status($module_id, $db_status, $module_value, $status, $title);
+ switch ($status) {
+ case STATUS_MODULE_NO_DATA:
+ // Not init status.
+ $status = 'notinit';
+ break;
+
+ case STATUS_MODULE_CRITICAL:
+ // Critical status.
+ $status = 'critical';
+ break;
+
+ case STATUS_MODULE_WARNING:
+ // Warning status.
+ $status = 'warning';
+ break;
+
+ case STATUS_MODULE_OK:
+ // Normal status.
+ $status = 'normal';
+ break;
+
+ case 3:
+ case -1:
+ default:
+ // Unknown status.
+ $status = 'unknown';
+ break;
+ }
+
+ $heatmap .= sprintf(
+ ' ',
+ 'rect_'.$cont,
+ $x,
+ $y,
+ $row,
+ $column,
+ $square_length,
+ $square_length,
+ $status,
+ random_int(1, 10)
+ );
+
+ $y += $square_length;
+ $row++;
+ if ((int) ($y + $square_length) > (int) $height) {
+ $y = 0;
+ $x += $square_length;
+ $row = 0;
+ $column++;
+ }
+
+ if ((int) ($x + $square_length) > (int) $width) {
+ $x = 0;
+ $y += $square_length;
+ $column = 0;
+ $row++;
+ }
+
+ $cont++;
+ }
+
+ $heatmap .= '';
+ $heatmap .= ' ';
+ $heatmap .= ' ';
+
+ return html_print_div(
+ [
+ 'content' => $heatmap,
+ 'style' => 'margin: 0 auto; width: fit-content; min-height: 285px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Return the status agents in heat map.
+ *
+ * @return string
+ */
+ public function getStatusHeatMapAgents():string
+ {
+ global $config;
+ $width = get_parameter('width', 350);
+ $height = get_parameter('height', 275);
+
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $sql = 'SELECT * FROM tagente a
+ LEFT JOIN tagent_secondary_group g ON g.id_agent = a.id_agente
+ WHERE g.id_group IN ('.$id_groups.') OR a.id_grupo IN ('.$id_groups.')';
+ $all_agents = db_get_all_rows_sql($sql);
+ if (empty($all_agents)) {
+ return null;
+ }
+
+ $total_agents = count($all_agents);
+
+ // Best square.
+ $high = (float) max($width, $height);
+ $low = 0.0;
+
+ while (abs($high - $low) > 0.000001) {
+ $mid = (($high + $low) / 2.0);
+ $midval = (floor($width / $mid) * floor($height / $mid));
+ if ($midval >= $total_agents) {
+ $low = $mid;
+ } else {
+ $high = $mid;
+ }
+ }
+
+ $square_length = min(($width / floor($width / $low)), ($height / floor($height / $low)));
+ // Print starmap.
+ $heatmap = sprintf(
+ '
',
+ $width,
+ $height
+ );
+
+ $heatmap .= '';
+ $row = 0;
+ $column = 0;
+ $x = 0;
+ $y = 0;
+ $cont = 1;
+
+ foreach ($all_agents as $key => $value) {
+ // Colour by status.
+ $status = agents_get_status_from_counts($value);
+
+ switch ($status) {
+ case 5:
+ // Not init status.
+ $status = 'notinit';
+ break;
+
+ case 1:
+ // Critical status.
+ $status = 'critical';
+ break;
+
+ case 2:
+ // Warning status.
+ $status = 'warning';
+ break;
+
+ case 0:
+ // Normal status.
+ $status = 'normal';
+ break;
+
+ case 3:
+ case -1:
+ default:
+ // Unknown status.
+ $status = 'unknown';
+ break;
+ }
+
+ $heatmap .= sprintf(
+ ' ',
+ 'rect_'.$cont,
+ $x,
+ $y,
+ $row,
+ $column,
+ $square_length,
+ $square_length,
+ $status,
+ random_int(1, 10)
+ );
+
+ $y += $square_length;
+ $row++;
+ if ((int) ($y + $square_length) > (int) $height) {
+ $y = 0;
+ $x += $square_length;
+ $row = 0;
+ $column++;
+ }
+
+ if ((int) ($x + $square_length) > (int) $width) {
+ $x = 0;
+ $y += $square_length;
+ $column = 0;
+ $row++;
+ }
+
+ $cont++;
+ }
+
+ $heatmap .= '';
+ $heatmap .= ' ';
+ $heatmap .= ' ';
+
+ return html_print_div(
+ [
+ 'content' => $heatmap,
+ 'style' => 'margin: 0 auto; width: fit-content; min-height: 285px;',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Return the status groups in heat map.
+ *
+ * @return string
+ */
+ public function getStatusHeatMapGroup():string
+ {
+ global $config;
+ $width = get_parameter('width', 350);
+ $height = get_parameter('height', 275);
+
+ // ACL Check.
+ $agent_a = check_acl($config['id_user'], 0, 'AR');
+ $agent_w = check_acl($config['id_user'], 0, 'AW');
+
+ $groups_list = groupview_get_groups_list(
+ $config['id_user'],
+ ($agent_a == true) ? 'AR' : (($agent_w == true) ? 'AW' : 'AR'),
+ true
+ );
+
+ $total_groups = $groups_list['counter'];
+ $groups = $groups_list['groups'];
+ // Best square.
+ $high = (float) max($width, $height);
+ $low = 0.0;
+
+ while (abs($high - $low) > 0.000001) {
+ $mid = (($high + $low) / 2.0);
+ $midval = (floor($width / $mid) * floor($height / $mid));
+ if ($midval >= $total_groups) {
+ $low = $mid;
+ } else {
+ $high = $mid;
+ }
+ }
+
+ $square_length = min(($width / floor($width / $low)), ($height / floor($height / $low)));
+ // Print starmap.
+ $heatmap = sprintf(
+ '
',
+ $width,
+ $height
+ );
+
+ $heatmap .= '';
+ $row = 0;
+ $column = 0;
+ $x = 0;
+ $y = 0;
+ $cont = 1;
+ foreach ($groups as $key => $value) {
+ if ($value['_name_'] === 'All') {
+ continue;
+ }
+
+ if ($value['_monitors_critical_'] > 0) {
+ $status = 'critical';
+ } else if ($value['_monitors_warning_'] > 0) {
+ $status = 'warning';
+ } else if (($value['_monitors_unknown_'] > 0) || ($value['_agents_unknown_'] > 0)) {
+ $status = 'unknown';
+ } else if ($value['_monitors_ok_'] > 0) {
+ $status = 'normal';
+ } else {
+ $status = 'unknown';
+ }
+
+ $heatmap .= sprintf(
+ ' ',
+ 'rect_'.$cont,
+ $x,
+ $y,
+ $row,
+ $column,
+ $square_length,
+ $square_length,
+ $status,
+ random_int(1, 10)
+ );
+
+ $y += $square_length;
+ $row++;
+ if ((int) ($y + $square_length) > (int) $height) {
+ $y = 0;
+ $x += $square_length;
+ $row = 0;
+ $column++;
+ }
+
+ if ((int) ($x + $square_length) > (int) $width) {
+ $x = 0;
+ $y += $square_length;
+ $column = 0;
+ $row++;
+ }
+
+ $cont++;
+ }
+
+ $heatmap .= '';
+ $heatmap .= ' ';
+ $heatmap .= ' ';
+
+ return html_print_div(
+ [
+ 'content' => $heatmap,
+ 'style' => 'margin: 0 auto; width: fit-content; min-height: 285px;',
+ ],
+ true
+ );
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/LogStorage.php b/pandora_console/include/lib/TacticalView/elements/LogStorage.php
new file mode 100644
index 0000000000..427b3c93c6
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/LogStorage.php
@@ -0,0 +1,219 @@
+title = __('Log storage');
+ $this->ajaxMethods = [
+ 'getStatus',
+ 'getTotalSources',
+ 'getStoredData',
+ 'getAgeOfStoredData',
+ ];
+ $this->interval = 300000;
+ $this->refreshConfig = [
+ 'status' => [
+ 'id' => 'status-log-storage',
+ 'method' => 'getStatus',
+ ],
+ 'total-source' => [
+ 'id' => 'total-source-log-storage',
+ 'method' => 'getTotalSources',
+ ],
+ 'total-lines' => [
+ 'id' => 'total-lines-log-storage',
+ 'method' => 'getStoredData',
+ ],
+ 'age' => [
+ 'id' => 'age-of-stored',
+ 'method' => 'getAgeOfStoredData',
+ ],
+ ];
+ }
+
+
+ /**
+ * Check if log storage module exist.
+ *
+ * @return boolean
+ */
+ public function isEnabled():bool
+ {
+ global $config;
+ if ((bool) $config['log_collector'] === true) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Returns the html status of log storage.
+ *
+ * @return string
+ */
+ public function getStatus():string
+ {
+ $classDisabled = '';
+ if ($this->isEnabled() === true) {
+ $value = $this->valueMonitoring('Log server connection');
+ $status = ((int) $value[0]['datos'] === 1) ? true : false;
+ if ($status === true) {
+ $image_status = html_print_image('images/status_check@svg.svg', true);
+ $text = html_print_div(
+ [
+ 'content' => __('Everything’s OK!'),
+ 'class' => 'status-text',
+ ],
+ true
+ );
+ } else {
+ $image_status = html_print_image('images/status_error@svg.svg', true);
+ $text = html_print_div(
+ [
+ 'content' => __('Something’s wrong'),
+ 'class' => 'status-text',
+ ],
+ true
+ );
+ }
+ } else {
+ $image_status = html_print_image('images/status_check@svg.svg', true);
+ $text = html_print_div(
+ [
+ 'content' => __('Everything’s OK!'),
+ 'class' => 'status-text',
+ ],
+ true
+ );
+ $classDisabled = 'alpha50';
+ }
+
+ $output = $image_status.$text;
+
+ return html_print_div(
+ [
+ 'content' => $output,
+ 'class' => 'flex_center margin-top-5 '.$classDisabled,
+ 'style' => 'margin: 0px 10px 10px 10px;',
+ 'id' => 'status-log-storage',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of total sources in log storage.
+ *
+ * @return string
+ */
+ public function getTotalSources():string
+ {
+ if ($this->isEnabled() === true) {
+ $data = $this->valueMonitoring('Total sources');
+ $value = format_numeric($data[0]['datos']);
+ } else {
+ $value = __('N/A');
+ }
+
+ return html_print_div(
+ [
+ 'content' => $value,
+ 'class' => 'text-l',
+ 'style' => 'margin: 0px 10px 0px 10px;',
+ 'id' => 'total-source-log-storage',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of lines in log storage.
+ *
+ * @return string
+ */
+ public function getStoredData():string
+ {
+ if ($this->isEnabled() === true) {
+ $data = $this->valueMonitoring('Total lines of data');
+ $value = format_numeric($data[0]['datos']);
+ } else {
+ $value = __('N/A');
+ }
+
+ return html_print_div(
+ [
+ 'content' => $value,
+ 'class' => 'text-l',
+ 'style' => 'margin: 0px 10px 0px 10px;',
+ 'id' => 'total-lines-log-storage',
+ ],
+ true
+ );
+ }
+
+
+ /**
+ * Returns the html of age of stored data.
+ *
+ * @return string
+ */
+ public function getAgeOfStoredData():string
+ {
+ $data = $this->valueMonitoring('Longest data archived');
+ $date = $data[0]['datos'];
+ if ($date > 0 && $this->isEnabled() === true) {
+ $interval = (time() - strtotime($date));
+ $days = format_numeric(($interval / 86400), 0);
+ } else {
+ $days = 'N/A';
+ }
+
+ return html_print_div(
+ [
+ 'content' => $days,
+ 'class' => 'text-l',
+ 'style' => 'margin: 0px 10px 0px 10px;',
+ 'id' => 'age-of-stored',
+ ],
+ true
+ );
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php b/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php
new file mode 100644
index 0000000000..eece06f65f
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php
@@ -0,0 +1,246 @@
+title = __('Monitoring elements');
+ }
+
+
+ /**
+ * Returns the html of the tags grouped by modules.
+ *
+ * @return string
+ */
+ public function getTagsGraph():string
+ {
+ $sql = 'SELECT name, count(*) AS total
+ FROM ttag_module t
+ LEFT JOIN ttag ta ON ta.id_tag = t.id_tag
+ GROUP BY t.id_tag
+ ORDER BY total DESC
+ LIMIT 10;';
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ foreach ($rows as $key => $row) {
+ if (empty($row['name']) === true) {
+ continue;
+ }
+
+ $labels[] = $this->controlSizeText($row['name']);
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => [
+ 'position' => 'bottom',
+ 'align' => 'right',
+ 'display' => false,
+ ],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Returns the html of the groups grouped by modules.
+ *
+ * @return string
+ */
+ public function getModuleGroupGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+ $sql = 'SELECT name, count(*) AS total
+ FROM tagente_modulo m
+ LEFT JOIN tagente a on a.id_agente = m.id_agente
+ LEFT JOIN tagent_secondary_group gs ON gs.id_agent = a.id_agente
+ LEFT JOIN tmodule_group g ON g.id_mg = m.id_module_group
+ WHERE name <> "" AND (a.id_grupo IN ('.$id_groups.') OR gs.id_group IN ('.$id_groups.'))
+ GROUP BY m.id_module_group
+ ORDER BY total DESC
+ LIMIT 10';
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ foreach ($rows as $key => $row) {
+ if (empty($row['name']) === true) {
+ continue;
+ }
+
+ $labels[] = $this->controlSizeText($row['name']);
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => [
+ 'position' => 'bottom',
+ 'align' => 'right',
+ 'display' => false,
+ ],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Returns the html of the agent grouped by modules.
+ *
+ * @return string
+ */
+ public function getAgentGroupsGraph():string
+ {
+ global $config;
+ $id_groups = array_keys(users_get_groups($config['id_user'], 'AR', false));
+
+ if (in_array(0, $id_groups) === false) {
+ foreach ($id_groups as $key => $id_group) {
+ if ((bool) check_acl_restricted_all($config['id_user'], $id_group, 'AR') === false) {
+ unset($id_groups[$key]);
+ }
+ }
+ }
+
+ $id_groups = implode(',', $id_groups);
+
+ $sql = 'SELECT gr.nombre, count(*) +
+ IFNULL((SELECT count(*) AS total
+ FROM tagente second_a
+ LEFT JOIN tagent_secondary_group second_g ON second_g.id_agent = second_a.id_agente
+ WHERE a.id_grupo = second_g.id_group AND second_g.id_group IN ('.$id_groups.')
+ GROUP BY second_g.id_group
+ ), 0) AS total
+ FROM tagente a
+ LEFT JOIN tgrupo gr ON gr.id_grupo = a.id_grupo
+ WHERE a.id_grupo IN ('.$id_groups.')
+ GROUP BY a.id_grupo
+ ORDER BY total DESC
+ LIMIT 10';
+ $rows = db_process_sql($sql);
+
+ $labels = [];
+ $data = [];
+ foreach ($rows as $key => $row) {
+ if (empty($row['nombre']) === true) {
+ continue;
+ }
+
+ $labels[] = $this->controlSizeText(io_safe_output($row['nombre']));
+ $data[] = $row['total'];
+ }
+
+ $options = [
+ 'labels' => $labels,
+ 'legend' => [
+ 'position' => 'bottom',
+ 'align' => 'right',
+ 'display' => false,
+ ],
+ 'cutout' => 80,
+ 'nodata_image' => ['width' => '100%'],
+ ];
+ $pie = ring_graph($data, $options);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+ /**
+ * Returns the html of monitoring by status.
+ *
+ * @return string
+ */
+ public function getMonitoringStatusGraph():string
+ {
+ $pie = graph_agent_status(false, '', '', true, true, false, true);
+ $output = html_print_div(
+ [
+ 'content' => $pie,
+ 'style' => 'margin: 0 auto; max-width: 80%; max-height: 220px;',
+ ],
+ true
+ );
+
+ return $output;
+ }
+
+
+}
diff --git a/pandora_console/include/lib/TacticalView/elements/NewsBoard.php b/pandora_console/include/lib/TacticalView/elements/NewsBoard.php
new file mode 100644
index 0000000000..3be2dd685f
--- /dev/null
+++ b/pandora_console/include/lib/TacticalView/elements/NewsBoard.php
@@ -0,0 +1,124 @@
+title = __('News Board');
+ }
+
+
+ /**
+ * Returns the html of the latest news.
+ *
+ * @return string
+ */
+ public function getNews():string
+ {
+ global $config;
+ $options = [];
+ $options['id_user'] = $config['id_user'];
+ $options['modal'] = false;
+ $options['limit'] = 7;
+ $news = get_news($options);
+
+ if (!empty($news)) {
+ $output = '
';
+ foreach ($news as $article) {
+ $default = false;
+ if ($article['text'] == '<p style="text-align: center; font-size: 13px;">Hello, congratulations, if you've arrived here you already have an operational monitoring console. Remember that our forums and online documentation are available 24x7 to get you out of any trouble. You can replace this message with a personalized one at Admin tools -&gt; Site news.</p> ') {
+ $article['subject'] = __('Welcome to Pandora FMS Console');
+ $default = true;
+ }
+
+ $text_bbdd = io_safe_output($article['text']);
+ $text = html_entity_decode($text_bbdd);
+
+ $output .= '
';
+ $output .= '';
+ $output .= '
';
+
+ if ($default) {
+ $output .= '
';
+ $output .= '
';
+ $output .= '
';
+ $output .= '
';
+
+ $output .= '
+
'.__('Welcome to our monitoring tool so grand,').'
+ '.__('Where data insights are at your command.').'
+ '.__('Sales, marketing, operations too,').'
+ '.__("Customer support, we've got you.").'
+
+
+
'.__('Our interface is user-friendly,').'
+ '.__("Customize your dashboard, it's easy.").'
+ '.__('Set up alerts and gain insights so keen,').'
+ '.__("Optimize your data, like you've never seen.").'
+
+
+
'.__('Unleash its power now, and join the pro league,').'
+ '.__('Unlock the potential of your data to intrigue.').'
+ '.__('Monitoring made simple, efficient and fun,').'
+ '.__('Discover a whole new way to get things done.').'
+
+
+
'.__('And take control of your IT once and for all.').'
+
+
'.__('You can replace this message with a personalized one at Admin tools -> Site news.').'
+ ';
+
+ $output .= '
';
+ } else {
+ $text = str_replace(''
);
diff --git a/pandora_console/mobile/operation/groups.php b/pandora_console/mobile/operation/groups.php
index c8c822966c..8a3a54d6e0 100644
--- a/pandora_console/mobile/operation/groups.php
+++ b/pandora_console/mobile/operation/groups.php
@@ -28,15 +28,9 @@ class Groups
function __construct()
{
$system = System::getInstance();
-
if ($system->checkACL($this->acl)) {
$this->correct_acl = true;
-
$this->groups = $this->getListGroups();
- // ~ foreach ($this->groups as $key => $group) {
- // ~ $this->status[$key] = $group['status'];
- // ~ unset($this->groups[$key]['status']);
- // ~ }
} else {
$this->correct_acl = false;
}
@@ -71,7 +65,6 @@ class Groups
private function show_group()
{
$ui = Ui::getInstance();
-
$ui->createPage();
$ui->createDefaultHeader(
__('Groups'),
@@ -88,10 +81,10 @@ class Groups
$ui->showFooter(false);
$ui->beginContent();
- $ui->contentAddHtml('
');
- $count = 0;
- $url_agent = 'index.php?page=agents&group=%s&status=%s';
- $url_modules = 'index.php?page=modules&group=%s&status=%s';
+ $ui->contentAddHtml('
');
+ $count = 0;
+ $url_agent = 'index.php?page=agents&group=%s&status=%s';
+ $url_modules = 'index.php?page=modules&group=%s&status=%s';
foreach ($this->groups as $group) {
// Calculate entire row color.
@@ -157,7 +150,15 @@ class Groups
$agents_counter .= ']';
if ($group['_iconImg_'] !== null) {
- $img_group = html_print_image('images/'.$group['_iconImg_'], true, false, false, false, false, true);
+ $img_group = html_print_image(
+ 'images/'.groups_get_icon($group['_id_']),
+ true,
+ false,
+ false,
+ false,
+ false,
+ true
+ );
}
$group['_iconImg_'] = ($group['_iconImg_'] == '') ? 'world.png' : $group['_iconImg_'];
@@ -218,15 +219,7 @@ class Groups
$count++;
}
- $ui->contentAddHtml('
');
-
- // $ui->contentAddHtml(ob_get_clean());
- // ~ $table = new Table();
- // ~ $table->setId('list_groups');
- // ~ $table->setClass('group_view');
- // ~ $table->importFromHash($this->groups);
- // ~ $table->setRowClass($this->status);
- // ~ $ui->contentAddHtml($table->getHTML());
+ $ui->contentAddHtml('
');
$ui->endContent();
$ui->showPage();
}
diff --git a/pandora_console/mobile/operation/module_graph.php b/pandora_console/mobile/operation/module_graph.php
index 815410cce8..491a77f526 100644
--- a/pandora_console/mobile/operation/module_graph.php
+++ b/pandora_console/mobile/operation/module_graph.php
@@ -276,12 +276,8 @@ class ModuleGraph
$(document).ready(function() {
function load_graph() {
$("#loading_graph").show();
-
- var heigth = $(document).height()
- - $(".ui-header").height()
- - $(".ui-collapsible").height()
- - 55;
- var width = $(document).width() - 25;
+ var heigth = $(document).width() / 2;
+ var width = $(document).width();
ajax_get_graph($("#id_module").val(), heigth, width, $("#server_id").val());
}
diff --git a/pandora_console/mobile/operation/visualmap.php b/pandora_console/mobile/operation/visualmap.php
index 54780f7d53..05a8ac3863 100644
--- a/pandora_console/mobile/operation/visualmap.php
+++ b/pandora_console/mobile/operation/visualmap.php
@@ -146,8 +146,7 @@ class Visualmap
$ui->retrieveViewPort();
}
- // Header.
- $this->height -= 40;
+ $this->height -= 45;
$this->visualmap = db_get_row(
'tlayout',
@@ -287,7 +286,8 @@ class Visualmap
];
}
- $ratio_t = $visualConsole->adjustToViewport($size, 'mobile');
+ $ratio_t = $visualConsole->adjustToViewport($size);
+
$visualConsoleData = $visualConsole->toArray();
$uniq = uniqid();
@@ -333,10 +333,6 @@ class Visualmap
$ratio_t
);
- $output .= '';
-
$visualConsoleItems = array_reduce(
$visualConsoleItems,
function ($carry, $item) {
diff --git a/pandora_console/operation/agentes/tactical.php b/pandora_console/operation/agentes/tactical.php
index dd8dd6ed1d..8dfabcd44f 100755
--- a/pandora_console/operation/agentes/tactical.php
+++ b/pandora_console/operation/agentes/tactical.php
@@ -27,14 +27,9 @@
*/
// Begin.
+use PandoraFMS\TacticalView\GeneralTacticalView;
+
global $config;
-
-require_once 'include/functions_events.php';
-require_once 'include/functions_servers.php';
-require_once 'include/functions_reporting.php';
-require_once 'include/functions_tactical.php';
-require_once $config['homedir'].'/include/functions_graph.php';
-
check_login();
if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'], 0, 'AW')) {
@@ -46,267 +41,5 @@ if (! check_acl($config['id_user'], 0, 'AR') && ! check_acl($config['id_user'],
return;
}
-ui_require_css_file('tactical');
-
-$is_admin = check_acl($config['id_user'], 0, 'PM');
-$user_strict = (bool) db_get_value('strict_acl', 'tusuario', 'id_user', $config['id_user']);
-
-$force_refresh = get_parameter('force_refresh', '');
-$refresh = get_parameter('refr', 0);
-if ($force_refresh == 1) {
- db_process_sql('UPDATE tgroup_stat SET utimestamp = 0');
-}
-
-$updated_time = '';
-if ($config['realtimestats'] == 0) {
- $updated_time = "
";
- $updated_time .= __('Last update').' : '.ui_print_timestamp(db_get_sql('SELECT min(utimestamp) FROM tgroup_stat'), true);
- $updated_time .= ' ';
-} else {
- // $updated_info = __("Updated at realtime");
- $updated_info = '';
-}
-
-// Header.
-ui_print_standard_header(
- __('Tactical view'),
- '',
- false,
- '',
- false,
- (array) $updated_time,
- [
- [
- 'link' => '',
- 'label' => __('Monitoring'),
- ],
- [
- 'link' => '',
- 'label' => __('Views'),
- ],
- ]
-);
-
-// Currently this function makes loading this page is impossible. Change
-// and create new function.
-$all_data = tactical_status_modules_agents($config['id_user'], false, 'AR');
-
-$data = [];
-
-$data['monitor_not_init'] = (int) $all_data['_monitors_not_init_'];
-$data['monitor_unknown'] = (int) $all_data['_monitors_unknown_'];
-$data['monitor_ok'] = (int) $all_data['_monitors_ok_'];
-$data['monitor_warning'] = (int) $all_data['_monitors_warning_'];
-$data['monitor_critical'] = (int) $all_data['_monitors_critical_'];
-$data['monitor_not_normal'] = (int) $all_data['_monitor_not_normal_'];
-$data['monitor_alerts'] = (int) $all_data['_monitors_alerts_'];
-$data['monitor_alerts_fired'] = (int) $all_data['_monitors_alerts_fired_'];
-$data['monitor_total'] = (int) $all_data['_monitor_total_'];
-
-$data['total_agents'] = (int) $all_data['_total_agents_'];
-
-$data['monitor_checks'] = (int) $all_data['_monitor_checks_'];
-
-
-// Percentages
-if (!empty($all_data)) {
- if ($data['monitor_not_normal'] > 0 && $data['monitor_checks'] > 0) {
- $data['monitor_health'] = format_numeric((100 - ($data['monitor_not_normal'] / ($data['monitor_checks'] / 100))), 1);
- } else {
- $data['monitor_health'] = 100;
- }
-
- if ($data['monitor_not_init'] > 0 && $data['monitor_checks'] > 0) {
- $data['module_sanity'] = format_numeric((100 - ($data['monitor_not_init'] / ($data['monitor_checks'] / 100))), 1);
- } else {
- $data['module_sanity'] = 100;
- }
-
- if (isset($data['alerts'])) {
- if ($data['monitor_alerts_fired'] > 0 && $data['alerts'] > 0) {
- $data['alert_level'] = format_numeric((100 - ($data['monitor_alerts_fired'] / ($data['alerts'] / 100))), 1);
- } else {
- $data['alert_level'] = 100;
- }
- } else {
- $data['alert_level'] = 100;
- $data['alerts'] = 0;
- }
-
- $data['monitor_bad'] = ($data['monitor_critical'] + $data['monitor_warning']);
-
- if ($data['monitor_bad'] > 0 && $data['monitor_checks'] > 0) {
- $data['global_health'] = format_numeric((100 - ($data['monitor_bad'] / ($data['monitor_checks'] / 100))), 1);
- } else {
- $data['global_health'] = 100;
- }
-
- $data['server_sanity'] = format_numeric((100 - $data['module_sanity']), 1);
-}
-
-echo '
';
-echo '';
-// ---------------------------------------------------------------------
-// The status horizontal bars (Global health, Monitor sanity...
-// ---------------------------------------------------------------------
-$bg_color = 'background-color: #222';
-if ($config['style'] !== 'pandora_black' && !is_metaconsole()) {
- $bg_color = 'background-color: #fff';
-}
-
-$table = new stdClass();
-$table->width = '100%';
-$table->class = 'info_table no-td-borders';
-$table->cellpadding = 2;
-$table->cellspacing = 2;
-$table->border = 0;
-$table->head = [];
-$table->data = [];
-$table->style = [$bg_color];
-
-$stats = reporting_get_stats_indicators($data, 120, 10, false);
-
-$statusTacticalTable = new stdClass();
-$statusTacticalTable->width = '100%';
-$statusTacticalTable->id = 'statusTacticalTable';
-$statusTacticalTable->class = 'status_tactical tactical_table bg_white';
-$statusTacticalTable->data = [];
-
-foreach ($stats as $key => $stat) {
- $statusTacticalTable->cellstyle['line_'.$key][0] = 'width: 40%;';
- $statusTacticalTable->style['line_'.$key][1] = 'width: 60%;';
- $statusTacticalTable->data['line_'.$key][0] = ''.$stat['title'].' ';
- $statusTacticalTable->data['line_'.$key][1] = $stat['graph'];
-}
-
-$status = html_print_table($statusTacticalTable, true);
-
-$table->rowclass = [];
-$table->rowclass[0] = 'w100p';
-$table->rowclass[1] = 'w100p';
-$table->rowclass[2] = 'w100p';
-$table->rowclass[3] = 'w100p';
-$table->rowclass[4] = 'w100p';
-$table->data[0][0] = $status;
-
-
-// ---------------------------------------------------------------------
-// Monitor checks
-// ---------------------------------------------------------------------
-$data_agents = [
- __('Critical') => $data['monitor_critical'],
- __('Warning') => $data['monitor_warning'],
- __('Normal') => $data['monitor_ok'],
- __('Unknown') => $data['monitor_unknown'],
- __('Not init') => $data['monitor_not_init'],
-];
-
-$table->data[1][0] = reporting_get_stats_alerts($data);
-$table->rowclass[1] = 'w100p';
-$table->data[2][0] = reporting_get_stats_modules_status($data, 180, 100, false, $data_agents);
-$table->data[3][0] = reporting_get_stats_agents_monitors($data);
-
-$table->rowclass[] = '';
-
-// ---------------------------------------------------------------------
-// Server performance
-// ---------------------------------------------------------------------
-if ($is_admin) {
- $table->data[4][0] = reporting_get_stats_servers();
- $table->rowclass[] = '';
-}
-
-ui_toggle(
- html_print_table($table, true),
- __('Report of State'),
- '',
- '',
- false
-);
-
-echo ' ';
-// Left column
-echo '';
-
-// ---------------------------------------------------------------------
-// Last events information
-// ---------------------------------------------------------------------
-if (check_acl($config['id_user'], 0, 'ER')) {
- $tags_condition = tags_get_acl_tags(false, 0, 'ER', 'event_condition');
- $event_filter = 'estado<>1';
- if (!empty($tags_condition)) {
- $event_filter .= " AND ($tags_condition)";
- }
-
- if ($config['event_view_hr']) {
- $event_filter .= ' AND utimestamp > (UNIX_TIMESTAMP(NOW()) - '.($config['event_view_hr'] * SECONDS_1HOUR).')';
- }
-
- $events = events_print_event_table($event_filter, 10, '100%', true, 0, true);
- ui_toggle(
- $events,
- __('Latest events'),
- '',
- '',
- false
- );
-}
-
-// ---------------------------------------------------------------------
-// Server information
-// ---------------------------------------------------------------------
-if ($is_admin) {
- $tiny = true;
- include $config['homedir'].'/godmode/servers/servers.build_table.php';
-}
-
-$out = '';
-$out .= '';
-$out .= ''.__('Event graph').' ';
-$out .= html_print_image('images/spinner.gif', true, ['id' => 'spinner_total_event_graph']);
-$out .= ' ';
-$out .= ' ';
-$out .= '
- '.__('Event graph by agent').' '.html_print_image('images/spinner.gif', true, ['id' => 'spinner_graphic_event_group']).' ';
-$out .= '
';
-
-
-ui_toggle(
- $out,
- __('Event graphs'),
- '',
- '',
- false
-);
-
-echo ' ';
-echo '
';
-?>
-
+$tacticalView = new GeneralTacticalView();
+$tacticalView->render();
diff --git a/pandora_console/operation/events/events.php b/pandora_console/operation/events/events.php
index e7a20b8642..4c3eae145e 100644
--- a/pandora_console/operation/events/events.php
+++ b/pandora_console/operation/events/events.php
@@ -338,8 +338,10 @@ if (is_metaconsole() === true
// Ajax responses.
if (is_ajax() === true) {
$get_events = (int) get_parameter('get_events', 0);
+ $external_url = (bool) get_parameter('external_url', 0);
$table_id = get_parameter('table_id', '');
$groupRecursion = (bool) get_parameter('groupRecursion', false);
+ $compact_date = (int) get_parameter('compact_date', 0);
// Datatables offset, limit.
$start = (int) get_parameter('start', 0);
@@ -354,8 +356,6 @@ if (is_ajax() === true) {
if ($get_events !== 0) {
try {
- ob_start();
-
$fields = [
'te.id_evento',
'te.id_agente',
@@ -471,7 +471,7 @@ if (is_ajax() === true) {
$data = array_reduce(
$events,
- function ($carry, $item) use ($table_id, &$redirection_form_id, $filter) {
+ function ($carry, $item) use ($table_id, &$redirection_form_id, $filter, $compact_date, $external_url) {
global $config;
$tmp = (object) $item;
@@ -612,6 +612,12 @@ if (is_ajax() === true) {
);
$user_timezone = users_get_user_by_id($_SESSION['id_usuario'])['timezone'];
+ if ($compact_date === 1) {
+ $options = ['prominent' => 'compact'];
+ } else {
+ $options = [];
+ }
+
if (empty($user_timezone) === true) {
if (date_default_timezone_get() !== $config['timezone']) {
$timezone = timezone_open(date_default_timezone_get());
@@ -626,16 +632,16 @@ if (is_ajax() === true) {
$total_sec = strtotime($tmp->timestamp);
$total_sec += $dif;
$last_contact = date($config['date_format'], $total_sec);
- $last_contact_value = ui_print_timestamp($last_contact, true);
+ $last_contact_value = ui_print_timestamp($last_contact, true, $options);
} else {
$title = date($config['date_format'], strtotime($tmp->timestamp));
- $value = ui_print_timestamp(strtotime($tmp->timestamp), true);
+ $value = ui_print_timestamp(strtotime($tmp->timestamp), true, $options);
$last_contact_value = '
'.$value.' ';
}
} else {
date_default_timezone_set($user_timezone);
$title = date($config['date_format'], strtotime($tmp->timestamp));
- $value = ui_print_timestamp(strtotime($tmp->timestamp), true);
+ $value = ui_print_timestamp(strtotime($tmp->timestamp), true, $options);
$last_contact_value = '
'.$value.' ';
}
@@ -736,8 +742,13 @@ if (is_ajax() === true) {
$criticity .= $color.'" data-title="'.$text.'" data-use_title_for_force_title="1">'.$text.'
';
$tmp->criticity = $criticity;
- // Add event severity to end of text.
- $evn = '
';
+ if (isset($external_url) === true && $external_url === true) {
+ $url = ui_get_full_url('index.php?sec=eventos&sec2=operation/events/events');
+ $evn = ' ';
+ } else {
+ // Add event severity to end of text.
+ $evn = ' ';
+ }
// Grouped events.
if ((int) $filter['group_rep'] === EVENT_GROUP_REP_EXTRAIDS) {
@@ -1223,32 +1234,15 @@ if (is_ajax() === true) {
'recordsFiltered' => $count,
]
);
- $response = ob_get_clean();
-
- // Clean output buffer.
- while (ob_get_level() !== 0) {
- ob_end_clean();
- }
} catch (Exception $e) {
echo json_encode(
['error' => $e->getMessage()]
);
}
-
- // If not valid it will throw an exception.
- json_decode($response);
- if (json_last_error() == JSON_ERROR_NONE) {
- // If valid dump.
- echo $response;
- } else {
- echo json_encode(
- ['error' => $response]
- );
- }
}
// AJAX section ends.
- exit;
+ return;
}
/*
@@ -3581,7 +3575,7 @@ function show_event_dialo(event, dialog_page) {
// History mode flag
var history = $("#hidden-history").val();
-
+ console.log(event);
jQuery.post(
ajax_file,
{
@@ -3599,7 +3593,7 @@ function show_event_dialo(event, dialog_page) {
.empty()
.append(data)
.dialog({
- title: event.evento,
+ title: event.event_title,
resizable: true,
draggable: true,
modal: true,
diff --git a/pandora_console/operation/netflow/nf_live_view.php b/pandora_console/operation/netflow/nf_live_view.php
index d5bf38e3ba..19cf892cb2 100644
--- a/pandora_console/operation/netflow/nf_live_view.php
+++ b/pandora_console/operation/netflow/nf_live_view.php
@@ -93,6 +93,7 @@ $filter['ip_src'] = get_parameter('ip_src', '');
$filter['dst_port'] = get_parameter('dst_port', '');
$filter['src_port'] = get_parameter('src_port', '');
$filter['advanced_filter'] = get_parameter('advanced_filter', '');
+$filter['router_ip'] = get_parameter('router_ip');
$filter['netflow_monitoring'] = (bool) get_parameter('netflow_monitoring');
$filter['netflow_monitoring_interval'] = (int) get_parameter('netflow_monitoring_interval', 300);
$filter['traffic_max'] = get_parameter('traffic_max', 0);
@@ -109,41 +110,64 @@ $interval_length = get_parameter('interval_length', NETFLOW_RES_MEDD);
$address_resolution = (int) get_parameter('address_resolution', ($config['netflow_get_ip_hostname'] ?? ''));
$filter_selected = (int) get_parameter('filter_selected', 0);
+
// Calculate range dates.
-$custom_date = get_parameter('custom_date', '0');
-$date = get_parameter('date', SECONDS_1DAY);
+$date_end = get_parameter('date_end', 0);
+$time_end = get_parameter('time_end');
+$datetime_end = strtotime($date_end.' '.$time_end);
+
+$custom_date = get_parameter('custom_date', 0);
+$range = get_parameter('date', SECONDS_1DAY);
+$date_text = get_parameter('date_text', SECONDS_1DAY);
+$date_init_less = (strtotime(date('Y/m/d')) - SECONDS_1DAY);
+$date_init = get_parameter('date_init', date(DATE_FORMAT, $date_init_less));
+$time_init = get_parameter('time_init', date(TIME_FORMAT, $date_init_less));
+$datetime_init = strtotime($date_init.' '.$time_init);
if ($custom_date === '1') {
- $date_init = get_parameter('date_init');
- $time_init = get_parameter('time_init');
- $date_end = get_parameter('date_end');
- $time_end = get_parameter('time_end');
- $date_from = strtotime($date_init.' '.$time_init);
- $date_to = strtotime($date_end.' '.$time_end);
+ if ($datetime_init >= $datetime_end) {
+ $datetime_init = $date_init_less;
+ }
+
+ $date_init = date('Y/m/d H:i:s', $datetime_init);
+ $date_end = date('Y/m/d H:i:s', $datetime_end);
+ $period = ($datetime_end - $datetime_init);
} else if ($custom_date === '2') {
- $date_text = get_parameter('date_text');
$date_units = get_parameter('date_units');
- $period = ($date_text * $date_units);
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = (strtotime($date_to) - $period);
-} else if (in_array($date, ['this_week', 'this_month', 'past_week', 'past_month'])) {
- if ($date === 'this_week') {
- $date_from = strtotime('last monday');
- $date_to = strtotime($date_from.' +6 days');
- } else if ($date === 'this_month') {
- $date_from = strtotime('first day of this month');
- $date_to = strtotime('last day of this month');
- } else if ($date === 'past_month') {
- $date_from = strtotime('first day of previous month');
- $date_to = strtotime('last day of previous month');
- } else if ($date === 'past_week') {
- $date_from = strtotime('monday', strtotime('last week'));
- $date_to = strtotime('sunday', strtotime('last week'));
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - ((int) $date_text * (int) $date_units)));
+ $period = (strtotime($date_end) - strtotime($date_init));
+} else if (in_array($range, ['this_week', 'this_month', 'past_week', 'past_month'])) {
+ if ($range === 'this_week') {
+ $monday = date('Y/m/d', strtotime('last monday'));
+
+ $sunday = date('Y/m/d', strtotime($monday.' +6 days'));
+ $period = (strtotime($sunday) - strtotime($monday));
+ $date_init = $monday;
+ $date_end = $sunday;
+ } else if ($range === 'this_month') {
+ $date_end = date('Y/m/d', strtotime('last day of this month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of this month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_month') {
+ $date_end = date('Y/m/d', strtotime('last day of previous month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of previous month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_week') {
+ $date_end = date('Y/m/d', strtotime('sunday', strtotime('last week')));
+ $first_of_week = date('Y/m/d', strtotime('monday', strtotime('last week')));
+ $date_init = $first_of_week;
+ $period = (strtotime($date_end) - strtotime($first_of_week));
}
} else {
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = ($date_to - $date);
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - $range));
+ $period = (strtotime($date_end) - strtotime($date_init));
}
+$date_from = strtotime($date_init);
+$date_to = strtotime($date_end);
// Read buttons.
// Change default value for not autoload default filter when load view.
$draw = get_parameter('draw_button', 1);
@@ -386,7 +410,7 @@ $radio_buttons .= __('No').' '.html_print_radio_button(
$advanced_toggle .= ' '.__('IP address resolution').' '.ui_print_help_tip(__('Resolve the IP addresses to get their hostnames.'), true).'';
$advanced_toggle .= '
'.$radio_buttons.' ';
-$advanced_toggle .= '
'.__('Source ip').' ';
+$advanced_toggle .= '
'.__('Netflow Source ip').' ';
$advanced_toggle .= '
'.html_print_input_text('router_ip', $filter['router_ip'], false, 40, 80, true).' ';
$advanced_toggle .= '';
@@ -949,11 +973,4 @@ ui_include_time_picker();
$("#text-date, #text-date_lower").datepicker({dateFormat: ""});
$.datepicker.regional[""];
-
- function nf_view_click_period() {
- var is_period = document.getElementById('checkbox-is_period').checked;
-
- document.getElementById('period_container').style.display = !is_period ? 'none' : 'flex';
- document.getElementById('end_date_container').style.display = is_period ? 'none' : 'flex';
- }
diff --git a/pandora_console/operation/network/network_report.php b/pandora_console/operation/network/network_report.php
index dd1614c716..4f5b91da5f 100644
--- a/pandora_console/operation/network/network_report.php
+++ b/pandora_console/operation/network/network_report.php
@@ -59,40 +59,63 @@ ui_include_time_picker();
// Calculate range dates.
-$custom_date = get_parameter('custom_date', '0');
-$date = get_parameter('date', SECONDS_1DAY);
+$date_end = get_parameter('date_end', 0);
+$time_end = get_parameter('time_end');
+$datetime_end = strtotime($date_end.' '.$time_end);
+
+$custom_date = get_parameter('custom_date', 0);
+$range = get_parameter('date', SECONDS_1DAY);
+$date_text = get_parameter('date_text', SECONDS_1DAY);
+$date_init_less = (strtotime(date('Y/m/d')) - SECONDS_1DAY);
+$date_init = get_parameter('date_init', date(DATE_FORMAT, $date_init_less));
+$time_init = get_parameter('time_init', date(TIME_FORMAT, $date_init_less));
+$datetime_init = strtotime($date_init.' '.$time_init);
if ($custom_date === '1') {
- $date_init = get_parameter('date_init');
- $time_init = get_parameter('time_init');
- $date_end = get_parameter('date_end');
- $time_end = get_parameter('time_end');
- $date_from = strtotime($date_init.' '.$time_init);
- $date_to = strtotime($date_end.' '.$time_end);
+ if ($datetime_init >= $datetime_end) {
+ $datetime_init = $date_init_less;
+ }
+
+ $date_init = date('Y/m/d H:i:s', $datetime_init);
+ $date_end = date('Y/m/d H:i:s', $datetime_end);
+ $period = ($datetime_end - $datetime_init);
} else if ($custom_date === '2') {
- $date_text = get_parameter('date_text');
$date_units = get_parameter('date_units');
- $period = ($date_text * $date_units);
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = (strtotime($date_to) - $period);
-} else if (in_array($date, ['this_week', 'this_month', 'past_week', 'past_month'])) {
- if ($date === 'this_week') {
- $date_from = strtotime('last monday');
- $date_to = strtotime($date_from.' +6 days');
- } else if ($date === 'this_month') {
- $date_from = strtotime('first day of this month');
- $date_to = strtotime('last day of this month');
- } else if ($date === 'past_month') {
- $date_from = strtotime('first day of previous month');
- $date_to = strtotime('last day of previous month');
- } else if ($date === 'past_week') {
- $date_from = strtotime('monday', strtotime('last week'));
- $date_to = strtotime('sunday', strtotime('last week'));
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - ((int) $date_text * (int) $date_units)));
+ $period = (strtotime($date_end) - strtotime($date_init));
+} else if (in_array($range, ['this_week', 'this_month', 'past_week', 'past_month'])) {
+ if ($range === 'this_week') {
+ $monday = date('Y/m/d', strtotime('last monday'));
+
+ $sunday = date('Y/m/d', strtotime($monday.' +6 days'));
+ $period = (strtotime($sunday) - strtotime($monday));
+ $date_init = $monday;
+ $date_end = $sunday;
+ } else if ($range === 'this_month') {
+ $date_end = date('Y/m/d', strtotime('last day of this month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of this month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_month') {
+ $date_end = date('Y/m/d', strtotime('last day of previous month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of previous month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_week') {
+ $date_end = date('Y/m/d', strtotime('sunday', strtotime('last week')));
+ $first_of_week = date('Y/m/d', strtotime('monday', strtotime('last week')));
+ $date_init = $first_of_week;
+ $period = (strtotime($date_end) - strtotime($first_of_week));
}
} else {
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = ($date_to - $date);
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - $range));
+ $period = (strtotime($date_end) - strtotime($date_init));
}
+$date_from = strtotime($date_init);
+$date_to = strtotime($date_end);
+
$filter_id = (int) get_parameter('filter_id', 0);
// Query params and other initializations.
diff --git a/pandora_console/operation/network/network_usage_map.php b/pandora_console/operation/network/network_usage_map.php
index 49245024df..f28b765673 100644
--- a/pandora_console/operation/network/network_usage_map.php
+++ b/pandora_console/operation/network/network_usage_map.php
@@ -85,40 +85,63 @@ ui_include_time_picker();
// Query params and other initializations.
$action = get_parameter('action', 'talkers');
// Calculate range dates.
-$custom_date = get_parameter('custom_date', '0');
-$date = get_parameter('date', SECONDS_1DAY);
+$date_end = get_parameter('date_end', 0);
+$time_end = get_parameter('time_end');
+$datetime_end = strtotime($date_end.' '.$time_end);
+
+$custom_date = get_parameter('custom_date', 0);
+$range = get_parameter('date', SECONDS_1DAY);
+$date_text = get_parameter('date_text', SECONDS_1DAY);
+$date_init_less = (strtotime(date('Y/m/d')) - SECONDS_1DAY);
+$date_init = get_parameter('date_init', date(DATE_FORMAT, $date_init_less));
+$time_init = get_parameter('time_init', date(TIME_FORMAT, $date_init_less));
+$datetime_init = strtotime($date_init.' '.$time_init);
if ($custom_date === '1') {
- $date_init = get_parameter('date_init');
- $time_init = get_parameter('time_init');
- $date_end = get_parameter('date_end');
- $time_end = get_parameter('time_end');
- $date_from = strtotime($date_init.' '.$time_init);
- $date_to = strtotime($date_end.' '.$time_end);
+ if ($datetime_init >= $datetime_end) {
+ $datetime_init = $date_init_less;
+ }
+
+ $date_init = date('Y/m/d H:i:s', $datetime_init);
+ $date_end = date('Y/m/d H:i:s', $datetime_end);
+ $period = ($datetime_end - $datetime_init);
} else if ($custom_date === '2') {
- $date_text = get_parameter('date_text');
$date_units = get_parameter('date_units');
- $period = ($date_text * $date_units);
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = (strtotime($date_to) - $period);
-} else if (in_array($date, ['this_week', 'this_month', 'past_week', 'past_month'])) {
- if ($date === 'this_week') {
- $date_from = strtotime('last monday');
- $date_to = strtotime($date_from.' +6 days');
- } else if ($date === 'this_month') {
- $date_from = strtotime('first day of this month');
- $date_to = strtotime('last day of this month');
- } else if ($date === 'past_month') {
- $date_from = strtotime('first day of previous month');
- $date_to = strtotime('last day of previous month');
- } else if ($date === 'past_week') {
- $date_from = strtotime('monday', strtotime('last week'));
- $date_to = strtotime('sunday', strtotime('last week'));
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - ((int) $date_text * (int) $date_units)));
+ $period = (strtotime($date_end) - strtotime($date_init));
+} else if (in_array($range, ['this_week', 'this_month', 'past_week', 'past_month'])) {
+ if ($range === 'this_week') {
+ $monday = date('Y/m/d', strtotime('last monday'));
+
+ $sunday = date('Y/m/d', strtotime($monday.' +6 days'));
+ $period = (strtotime($sunday) - strtotime($monday));
+ $date_init = $monday;
+ $date_end = $sunday;
+ } else if ($range === 'this_month') {
+ $date_end = date('Y/m/d', strtotime('last day of this month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of this month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_month') {
+ $date_end = date('Y/m/d', strtotime('last day of previous month'));
+ $first_of_month = date('Y/m/d', strtotime('first day of previous month'));
+ $date_init = $first_of_month;
+ $period = (strtotime($date_end) - strtotime($first_of_month));
+ } else if ($range === 'past_week') {
+ $date_end = date('Y/m/d', strtotime('sunday', strtotime('last week')));
+ $first_of_week = date('Y/m/d', strtotime('monday', strtotime('last week')));
+ $date_init = $first_of_week;
+ $period = (strtotime($date_end) - strtotime($first_of_week));
}
} else {
- $date_to = strtotime(date('Y-m-d H:i:s'));
- $date_from = ($date_to - $date);
+ $date_end = date('Y/m/d H:i:s');
+ $date_init = date('Y/m/d H:i:s', (strtotime($date_end) - $range));
+ $period = (strtotime($date_end) - strtotime($date_init));
}
+$date_from = strtotime($date_init);
+$date_to = strtotime($date_end);
+
$advanced_filter = get_parameter('advanced_filter', '');
$top = (int) get_parameter('top', 10);
diff --git a/pandora_console/operation/visual_console/public_view.php b/pandora_console/operation/visual_console/public_view.php
index 6fdac1b949..6fd892b76f 100644
--- a/pandora_console/operation/visual_console/public_view.php
+++ b/pandora_console/operation/visual_console/public_view.php
@@ -62,6 +62,12 @@ require_once 'include/functions_visual_map.php';
$hash = (string) get_parameter('hash');
+// For public link issue.
+$force_instant_logout = true;
+if (isset($config['id_user']) === true) {
+ $force_instant_logout = false;
+}
+
// Check input hash.
// DO NOT move it after of get parameter user id.
if (User::validatePublicHash($hash) !== true) {
@@ -316,3 +322,10 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
}
});
+
+
+
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+
+
+
+
+ getLogSizeStatus(); ?>
+
+
+
+
+
+
+
+ getServerStatus(); ?>
+
+
+
+
+
+
+
+ getCPULoadGraph(); ?>
+
+
+
+
+
+
+
+
+ getLicenseUsageGraph(); ?>
+
+
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+ getModuleGroupGraph(); ?>
+
+
+
+
+
+ getMonitoringStatusGraph(); ?>
+
+
+
+ getAgentGroupsGraph(); ?>
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+
+ getStatus(); ?>
+
+
+
+
+
+ getDataRecords(); ?>
+
+
+
+
+
+
+
+ getStringRecords(); ?>
+
+
+
+
+
+ getEvents(); ?>
+
+
+
+
+
+
+ getReadsGraph(); ?>
+
+
+
+
+
+ getWritesGraph(); ?>
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+ getNews(); ?>
+
+
+
+
+
+ title; ?>
+
+
+
+ loading(); ?>
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+ getStatus(); ?>
+
+
+
+
+
+ getTotalSources(); ?>
+
+
+
+
+
+
+
+ getStoredData(); ?>
+
+
+
+
+
+
+ getAgeOfStoredData(); ?>
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+ getQueues(); ?>
+
+
+
+
+
+ getTotalSources(); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+ getCurrentlyTriggered(); ?>
+
+
+
+
+
+ getActiveAlerts(); ?>
+
+
+ checkAclUserList() === true) : ?>
+
+
+ getDataTableUsers(); ?>
+
+
+
+
+ checkAcl() === true) : ?>
+
+
+
+ title; ?>
+
+
+
+
+
+ getDataTableEvents(); ?>
+
+
+
+
+
+
+
+
+
+
+
+ title; ?>
+
+
+
+
+
+
+
+
+ getTotalAgents(); ?>
+
+
+
+
+
+ getAlerts(); ?>
+
+
+
+ getDataTableGroups(); ?>
+
+
+
+
+
+ getOperatingSystemGraph(); ?>
+
+
+
+ getStatusGraph(); ?>
+
+
+
+
+
+
+ checkAcl() === true) : ?>
+
+
+ title; ?>
+
+ list(); ?>
+
+
+
+
+
+{"google_maps_description"} = 0;
$pa_config->{'openstreetmaps_description'} = 0;
$pa_config->{"eventserver"} = 1; # 4.0
- $pa_config->{"correlationserver"} = 0; # 757
- $pa_config->{"correlation_threshold"} = 30; # 757
+ $pa_config->{"eventserver_threads"} = 1; # 4.0
+ $pa_config->{"logserver"} = 1; # 7.774
+ $pa_config->{"logserver_threads"} = 1; # 7.774
$pa_config->{"event_window"} = 3600; # 4.0
$pa_config->{"log_window"} = 3600; # 7.741
$pa_config->{"elastic_query_size"} = 10; # 7.754 Elements per request (ELK)
@@ -580,6 +581,8 @@ sub pandora_load_config {
$pa_config->{"repl_dbuser"} = undef; # 7.0.770
$pa_config->{"repl_dbpass"} = undef; # 7.0.770
+ $pa_config->{"ssl_verify"} = 0; # 7.0 774
+
# Check for UID0
if ($pa_config->{"quiet"} != 0){
if ($> == 0){
@@ -801,14 +804,17 @@ sub pandora_load_config {
$pa_config->{"transactional_pool"} = $pa_config->{"incomingdir"} . "/" . $tbuf;
}
}
- elsif ($parametro =~ m/^eventserver\s+([0-9]*)/i) {
+ elsif ($parametro =~ m/^eventserver\s+([0-1])/i) {
$pa_config->{'eventserver'}= clean_blank($1);
}
- elsif ($parametro =~ m/^correlationserver\s+([0-9]*)/i) {
- $pa_config->{'correlationserver'}= clean_blank($1);
+ elsif ($parametro =~ m/^eventserver_threads\s+([0-9]*)/i) {
+ $pa_config->{'eventserver_threads'}= clean_blank($1);
}
- elsif ($parametro =~ m/^correlation_threshold\s+([0-9]*)/i) {
- $pa_config->{'correlation_threshold'}= clean_blank($1);
+ elsif ($parametro =~ m/^logserver\s+([0-1])/i) {
+ $pa_config->{'logserver'}= clean_blank($1);
+ }
+ elsif ($parametro =~ m/^logserver_threads\s+([0-9]*)/i) {
+ $pa_config->{'logserver_threads'}= clean_blank($1);
}
elsif ($parametro =~ m/^icmpserver\s+([0-9]*)/i) {
$pa_config->{'icmpserver'}= clean_blank($1);
@@ -1391,6 +1397,9 @@ sub pandora_load_config {
elsif ($parametro =~ m/^repl_dbpass\s(.*)/i) {
$pa_config->{'repl_dbpass'} = clean_blank($1);
}
+ elsif ($parametro =~ m/^ssl_verify\s+([0-1])/i) {
+ $pa_config->{'ssl_verify'} = clean_blank($1);
+ }
} # end of loop for parameter #
# The DB host was overridden by pandora_ha.
diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm
index 58815a4ff9..6da2b77b41 100644
--- a/pandora_server/lib/PandoraFMS/Core.pm
+++ b/pandora_server/lib/PandoraFMS/Core.pm
@@ -313,6 +313,7 @@ our @ServerTypes = qw (
icmpserver
snmpserver
satelliteserver
+ transactionalserver
mfserver
syncserver
wuxserver
@@ -323,6 +324,7 @@ our @ServerTypes = qw (
correlationserver
ncmserver
netflowserver
+ logserver
);
our @AlertStatus = ('Execute the alert', 'Do not execute the alert', 'Do not execute the alert, but increment its internal counter', 'Cease the alert', 'Recover the alert', 'Reset internal counter');
@@ -804,9 +806,9 @@ Process an alert given the status returned by pandora_evaluate_alert.
=cut
##########################################################################
-sub pandora_process_alert ($$$$$$$$;$$) {
+sub pandora_process_alert ($$$$$$$$;$) {
my ($pa_config, $data, $agent, $module, $alert, $rc, $dbh, $timestamp,
- $extra_macros, $is_correlated_alert) = @_;
+ $extra_macros) = @_;
if (defined ($agent)) {
logger ($pa_config, "Processing alert '" . safe_output($alert->{'name'}) . "' for agent '" . safe_output($agent->{'nombre'}) . "': " . (defined ($AlertStatus[$rc]) ? $AlertStatus[$rc] : 'Unknown status') . ".", 10);
@@ -814,15 +816,21 @@ sub pandora_process_alert ($$$$$$$$;$$) {
else {
logger ($pa_config, "Processing alert '" . safe_output($alert->{'name'}) . "': " . (defined ($AlertStatus[$rc]) ? $AlertStatus[$rc] : 'Unknown status') . ".", 10);
}
-
+
# Simple or event alert?
my ($id, $table) = (undef, undef);
if (defined ($alert->{'id_template_module'})) {
$id = $alert->{'id_template_module'};
$table = 'talert_template_modules';
- } else {
+ } elsif (defined ($alert->{'_log_alert'})) {
+ $id = $alert->{'id'};
+ $table = 'tlog_alert';
+ } elsif (defined ($alert->{'_event_alert'})) {
$id = $alert->{'id'};
$table = 'tevent_alert';
+ } else {
+ logger($pa_config, "pandora_process_alert received invalid data", 10);
+ return;
}
# Do not execute
@@ -874,10 +882,10 @@ sub pandora_process_alert ($$$$$$$$;$$) {
if ($pa_config->{'alertserver'} == 1 || $pa_config->{'alertserver_queue'} == 1) {
pandora_queue_alert($pa_config, $dbh, [$data, $agent, $module,
- $alert, 0, $timestamp, 0, $extra_macros, $is_correlated_alert]);
+ $alert, 0, $timestamp, 0, $extra_macros]);
} else {
pandora_execute_alert ($pa_config, $data, $agent, $module, $alert, 0, $dbh,
- $timestamp, 0, $extra_macros, $is_correlated_alert);
+ $timestamp, 0, $extra_macros);
}
return;
}
@@ -920,10 +928,10 @@ sub pandora_process_alert ($$$$$$$$;$$) {
if ($pa_config->{'alertserver'} == 1 || $pa_config->{'alertserver_queue'} == 1) {
pandora_queue_alert($pa_config, $dbh, [$data, $agent, $module,
- $alert, 1, $timestamp, 0, $extra_macros, $is_correlated_alert]);
+ $alert, 1, $timestamp, 0, $extra_macros]);
} else {
pandora_execute_alert ($pa_config, $data, $agent, $module, $alert, 1,
- $dbh, $timestamp, 0, $extra_macros, $is_correlated_alert);
+ $dbh, $timestamp, 0, $extra_macros);
}
return;
}
@@ -939,7 +947,7 @@ Execute the given alert.
sub pandora_execute_alert {
my ($pa_config, $data, $agent, $module,
$alert, $alert_mode, $dbh, $timestamp, $forced_alert,
- $extra_macros, $is_correlated_alert) = @_;
+ $extra_macros) = @_;
# 'in-process' events can inhibit alers too.
if ($pa_config->{'event_inhibit_alerts'} == 1 && $alert_mode != RECOVERED_ALERT) {
@@ -1029,7 +1037,7 @@ sub pandora_execute_alert {
}
}
# Event alert
- else {
+ elsif (defined($alert->{'_event_alert'})) {
if ($alert_mode == RECOVERED_ALERT) {
@actions = get_db_rows ($dbh, 'SELECT talert_actions.name as action_name, tevent_alert_action.*, talert_actions.*, talert_commands.*
FROM tevent_alert_action, talert_actions, talert_commands
@@ -1060,6 +1068,38 @@ sub pandora_execute_alert {
$alert->{'id_alert_action'});
}
}
+ # Log alert.
+ elsif (defined($alert->{'_log_alert'})) {
+ if ($alert_mode == RECOVERED_ALERT) {
+ @actions = get_db_rows ($dbh, 'SELECT talert_actions.name as action_name, tlog_alert_action.*, talert_actions.*, talert_commands.*
+ FROM tlog_alert_action, talert_actions, talert_commands
+ WHERE tlog_alert_action.id_alert_action = talert_actions.id
+ AND talert_actions.id_alert_command = talert_commands.id
+ AND tlog_alert_action.id_log_alert = ?
+ AND ((fires_min = 0 AND fires_max = 0)
+ OR ? >= fires_min)',
+ $alert->{'id'}, $alert->{'times_fired'});
+ } else {
+ @actions = get_db_rows ($dbh, 'SELECT talert_actions.name as action_name, tlog_alert_action.*, talert_actions.*, talert_commands.*
+ FROM tlog_alert_action, talert_actions, talert_commands
+ WHERE tlog_alert_action.id_alert_action = talert_actions.id
+ AND talert_actions.id_alert_command = talert_commands.id
+ AND tlog_alert_action.id_log_alert = ?
+ AND ((fires_min = 0 AND fires_max = 0)
+ OR (fires_min <= fires_max AND ? >= fires_min AND ? <= fires_max)
+ OR (fires_min > fires_max AND ? >= fires_min))',
+ $alert->{'id'}, $alert->{'times_fired'}, $alert->{'times_fired'}, $alert->{'times_fired'});
+ }
+
+ # Get default action
+ if ($#actions < 0) {
+ @actions = get_db_rows ($dbh, 'SELECT talert_actions.name as action_name, talert_actions.*, talert_commands.*
+ FROM talert_actions, talert_commands
+ WHERE talert_actions.id = ?
+ AND talert_actions.id_alert_command = talert_commands.id',
+ $alert->{'id_alert_action'});
+ }
+ }
# No actions defined
if ($#actions < 0) {
@@ -1148,8 +1188,33 @@ sub pandora_execute_alert {
#If we've spotted an alert recovered, we set the new event's severity to 2 (NORMAL), otherwise the original value is maintained.
my ($text, $event, $severity) = ($alert_mode == RECOVERED_ALERT) ? ('recovered', 'alert_recovered', 2) : ('fired', 'alert_fired', $alert->{'priority'});
- if (defined($is_correlated_alert) && $is_correlated_alert == 1) {
- $text = "Correlated alert $text";
+ if (defined($alert->{'_event_alert'})) {
+ $text = "Event alert $text";
+ pandora_event (
+ $pa_config,
+ "$text (" . safe_output($alert->{'name'}) . ") ",
+ (defined ($agent) ? $agent->{'id_grupo'} : 0),
+ # id agent.
+ 0,
+ $severity,
+ (defined ($alert->{'id_template_module'}) ? $alert->{'id_template_module'} : 0),
+ # id agent module.
+ 0,
+ $event,
+ 0,
+ $dbh,
+ 'monitoring_server',
+ '',
+ '',
+ '',
+ '',
+ $critical_instructions,
+ $warning_instructions,
+ $unknown_instructions,
+ p_encode_json($pa_config, $custom_data)
+ );
+ } elsif (defined($alert->{'_log_alert'})) {
+ $text = "Log alert $text";
pandora_event (
$pa_config,
"$text (" . safe_output($alert->{'name'}) . ") ",
diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm
index e6e8e211cc..d26ad54312 100644
--- a/pandora_server/lib/PandoraFMS/PluginTools.pm
+++ b/pandora_server/lib/PandoraFMS/PluginTools.pm
@@ -34,7 +34,7 @@ our @ISA = qw(Exporter);
# version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.773.3";
-my $pandora_build = "231019";
+my $pandora_build = "231023";
our $VERSION = $pandora_version." ".$pandora_build;
our %EXPORT_TAGS = ( 'all' => [ qw() ] );
diff --git a/pandora_server/lib/PandoraFMS/Tools.pm b/pandora_server/lib/PandoraFMS/Tools.pm
index c9a89938d7..4af9292467 100755
--- a/pandora_server/lib/PandoraFMS/Tools.pm
+++ b/pandora_server/lib/PandoraFMS/Tools.pm
@@ -67,7 +67,6 @@ our @EXPORT = qw(
INVENTORYSERVER
WEBSERVER
EVENTSERVER
- CORRELATIONSERVER
ICMPSERVER
SNMPSERVER
SATELLITESERVER
@@ -79,6 +78,7 @@ our @EXPORT = qw(
MIGRATIONSERVER
NCMSERVER
NETFLOWSERVER
+ LOGSERVER
METACONSOLE_LICENSE
OFFLINE_LICENSE
DISCOVERY_HOSTDEVICES
@@ -205,9 +205,10 @@ use constant SYSLOGSERVER => 18;
use constant PROVISIONINGSERVER => 19;
use constant MIGRATIONSERVER => 20;
use constant ALERTSERVER => 21;
-use constant CORRELATIONSERVER => 22;
+use constant CORRELATIONSERVER => 22; # Deprecated.
use constant NCMSERVER => 23;
use constant NETFLOWSERVER => 24;
+use constant LOGSERVER => 25;
# Module status
use constant MODULE_NORMAL => 0;
@@ -2974,6 +2975,7 @@ sub get_server_name {
return "CORRELATIONSERVER" if ($server_type eq CORRELATIONSERVER);
return "NCMSERVER" if ($server_type eq NCMSERVER);
return "NETFLOWSERVER" if ($server_type eq NETFLOWSERVER);
+ return "LOGSERVER" if ($server_type eq LOGSERVER);
return "UNKNOWN";
}
diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec
index b0994b4bb5..3044d2cba6 100644
--- a/pandora_server/pandora_server.redhat.spec
+++ b/pandora_server/pandora_server.redhat.spec
@@ -7,7 +7,7 @@
%define debug_package %{nil}
%define name pandorafms_server
%define version 7.0NG.773.3
-%define release 231019
+%define release 231023
Summary: Pandora FMS Server
Name: %{name}
diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec
index 5e78696339..6ac371b853 100644
--- a/pandora_server/pandora_server.spec
+++ b/pandora_server/pandora_server.spec
@@ -4,7 +4,7 @@
%global __os_install_post %{nil}
%define name pandorafms_server
%define version 7.0NG.773.3
-%define release 231019
+%define release 231023
Summary: Pandora FMS Server
Name: %{name}
diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer
index c65efdfb3a..4bec5edfc5 100755
--- a/pandora_server/pandora_server_installer
+++ b/pandora_server/pandora_server_installer
@@ -9,7 +9,7 @@
# **********************************************************************
PI_VERSION="7.0NG.773.3"
-PI_BUILD="231019"
+PI_BUILD="231023"
MODE=$1
if [ $# -gt 1 ]; then
diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl
index b6e8e77248..2272222299 100755
--- a/pandora_server/util/pandora_db.pl
+++ b/pandora_server/util/pandora_db.pl
@@ -35,7 +35,7 @@ use PandoraFMS::Config;
use PandoraFMS::DB;
# version: define current version
-my $version = "7.0NG.773.3 Build 231019";
+my $version = "7.0NG.773.3 Build 231023";
# Pandora server configuration
my %conf;
diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl
index 29b39101b2..7bedc825b3 100755
--- a/pandora_server/util/pandora_manage.pl
+++ b/pandora_server/util/pandora_manage.pl
@@ -36,7 +36,7 @@ use Encode::Locale;
Encode::Locale::decode_argv;
# version: define current version
-my $version = "7.0NG.773.3 Build 231019";
+my $version = "7.0NG.773.3 Build 231023";
# save program name for logging
my $progname = basename($0);
diff --git a/visual_console_client/src/Item.ts b/visual_console_client/src/Item.ts
index 9c143e85e9..356421d9d2 100644
--- a/visual_console_client/src/Item.ts
+++ b/visual_console_client/src/Item.ts
@@ -19,7 +19,8 @@ import {
addMovementListener,
debounce,
addResizementListener,
- t
+ t,
+ parseFloatOr
} from "./lib";
import TypedEvent, { Listener, Disposable } from "./lib/TypedEvent";
import { FormContainer, InputGroup } from "./Form";
@@ -65,8 +66,9 @@ export interface ItemProps extends Position, Size {
aclGroupId: number | null;
cacheExpiration: number | null;
colorStatus: string;
- cellId: number | null;
+ cellId: string | null;
alertOutline: boolean;
+ ratio: number | null;
}
export interface ItemClickEvent {
@@ -143,8 +145,9 @@ export function itemBasePropsDecoder(data: AnyObject): ItemProps | never {
aclGroupId: parseIntOr(data.aclGroupId, null),
cacheExpiration: parseIntOr(data.cacheExpiration, null),
colorStatus: notEmptyStringOr(data.colorStatus, "#CCC"),
- cellId: parseIntOr(data.cellId, null),
+ cellId: notEmptyStringOr(data.cellId, ""),
alertOutline: parseBoolean(data.alertOutline),
+ ratio: parseFloatOr(data.ratio, null),
...sizePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
...positionPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
};
@@ -506,6 +509,7 @@ abstract class VisualConsoleItem
{
// Resize element.
this.resizeElement(this.itemProps.width, this.itemProps.height);
+
// Set label position.
this.changeLabelPosition(this.itemProps.labelPosition);
}
@@ -533,6 +537,7 @@ abstract class VisualConsoleItem {
if (this.props.isOnTop) {
box.classList.add("is-on-top");
}
+
box.style.left = `${this.props.x}px`;
box.style.top = `${this.props.y}px`;
@@ -639,26 +644,6 @@ abstract class VisualConsoleItem {
table.appendChild(row);
table.appendChild(emptyRow2);
table.style.textAlign = "center";
-
- // Change the table size depending on its position.
- switch (this.props.labelPosition) {
- case "up":
- case "down":
- if (this.props.width > 0) {
- table.style.width = `${this.props.width}px`;
- table.style.height = "";
- }
- break;
- case "left":
- case "right":
- if (this.props.height > 0) {
- table.style.width = "";
- table.style.height = `${this.props.height}px`;
- }
- break;
- }
-
- // element.innerHTML = this.props.label;
element.appendChild(table);
}
@@ -822,6 +807,14 @@ abstract class VisualConsoleItem {
prevMeta: ItemMeta | null = null
): void {
if (prevProps) {
+ if (this.props.ratio !== 1 && this.props.type != ItemType.LINE_ITEM) {
+ this.elementRef.style.transform = `scale(${
+ this.props.ratio ? this.props.ratio : 1
+ })`;
+ this.elementRef.style.transformOrigin = "left top";
+ this.elementRef.style.minWidth = "max-content";
+ this.elementRef.style.minHeight = "max-content";
+ }
this.updateDomElement(this.childElementRef);
}
// Move box.
@@ -835,6 +828,7 @@ abstract class VisualConsoleItem {
this.updateDomElement(this.childElementRef);
}
}
+
// Resize box.
if (!prevProps || this.sizeChanged(prevProps, this.props)) {
this.resizeElement(this.props.width, this.props.height);
@@ -852,6 +846,7 @@ abstract class VisualConsoleItem {
if (oldLabelHtml !== newLabelHtml) {
this.labelElementRef.innerHTML = newLabelHtml;
}
+
// Change label position.
if (!prevProps || prevProps.labelPosition !== this.props.labelPosition) {
this.changeLabelPosition(this.props.labelPosition);
@@ -864,6 +859,7 @@ abstract class VisualConsoleItem {
this.elementRef.classList.remove("is-on-top");
}
}
+
// Change link.
if (prevProps && prevProps.isLinkEnabled !== this.props.isLinkEnabled) {
const container = this.createContainerDomElement();
diff --git a/visual_console_client/src/VisualConsole.ts b/visual_console_client/src/VisualConsole.ts
index a74ae062e8..0b3ec4bdbf 100644
--- a/visual_console_client/src/VisualConsole.ts
+++ b/visual_console_client/src/VisualConsole.ts
@@ -300,11 +300,11 @@ export default class VisualConsole {
item.props.type !== 13 &&
item.props.type !== 21
) {
- const movement_x = e.newPosition.x - e.item.props.x;
- const movement_y = e.newPosition.y - e.item.props.y;
+ const movementX = e.newPosition.x - e.item.props.x;
+ const movementY = e.newPosition.y - e.item.props.y;
- let newX = item.props.x + movement_x;
- let newY = item.props.y + movement_y;
+ let newX = item.props.x + movementX;
+ let newY = item.props.y + movementY;
if (newX > this.props.width) {
newX = this.props.width;
@@ -682,6 +682,7 @@ export default class VisualConsole {
return;
}
let line = this.elementsById[lineId] as Line;
+
if (line.props) {
let startX = line.props.startPosition.x;
let startY = line.props.startPosition.y;
@@ -792,7 +793,20 @@ export default class VisualConsole {
*/
public addElement(item: AnyObject, context: this = this) {
try {
+ if (item.ratio == null) {
+ item.ratio = 1;
+ }
+
+ item.x *= item.ratio;
+ item.y *= item.ratio;
+ if (item.type == ItemType.LINE_ITEM) {
+ item.startX *= item.ratio;
+ item.startY *= item.ratio;
+ item.endX *= item.ratio;
+ item.endY *= item.ratio;
+ }
const itemInstance = itemInstanceFrom(item);
+
// Add the item to the list.
context.elementsById[itemInstance.props.id] = itemInstance;
context.elementIds.push(itemInstance.props.id);
@@ -815,6 +829,15 @@ export default class VisualConsole {
itemInstance.onResizeFinished(context.handleElementResizementFinished);
}
+ if (item.ratio !== 1 && item.type != ItemType.LINE_ITEM) {
+ itemInstance.elementRef.style.transform = `scale(${
+ item.ratio ? item.ratio : 1
+ })`;
+ itemInstance.elementRef.style.transformOrigin = "left top";
+ itemInstance.elementRef.style.minWidth = "max-content";
+ itemInstance.elementRef.style.minHeight = "max-content";
+ }
+
// Add the item to the DOM.
context.containerRef.append(itemInstance.elementRef);
return itemInstance;
@@ -854,6 +877,16 @@ export default class VisualConsole {
} else {
// Update item.
try {
+ if (item.ratio != null) {
+ item.x *= item.ratio;
+ item.y *= item.ratio;
+ if (item.type == ItemType.LINE_ITEM) {
+ item.startX *= item.ratio;
+ item.startY *= item.ratio;
+ item.endX *= item.ratio;
+ item.endY *= item.ratio;
+ }
+ }
this.elementsById[item.id].props = decodeProps(item);
} catch (error) {
console.error(
@@ -1103,8 +1136,14 @@ export default class VisualConsole {
position: Position,
element: Item
): Position {
- let x = position.x + element.elementRef.clientWidth / 2;
- let y = position.y + element.elementRef.clientHeight / 2;
+ let ratio = 1;
+ if (element.props.ratio != null) {
+ ratio = element.props.ratio;
+ }
+
+ let x = position.x + (element.elementRef.clientWidth / 2) * ratio;
+ let y = position.y + (element.elementRef.clientHeight / 2) * ratio;
+
if (
typeof element.props.label !== "undefined" ||
element.props.label !== "" ||
@@ -1114,33 +1153,38 @@ export default class VisualConsole {
case "up":
y =
position.y +
- (element.elementRef.clientHeight +
+ ((element.elementRef.clientHeight +
element.labelElementRef.clientHeight) /
- 2;
+ 2) *
+ ratio;
break;
case "down":
y =
position.y +
- (element.elementRef.clientHeight -
+ ((element.elementRef.clientHeight -
element.labelElementRef.clientHeight) /
- 2;
+ 2) *
+ ratio;
break;
case "right":
x =
position.x +
- (element.elementRef.clientWidth -
+ ((element.elementRef.clientWidth -
element.labelElementRef.clientWidth) /
- 2;
+ 2) *
+ ratio;
break;
case "left":
x =
position.x +
- (element.elementRef.clientWidth +
+ ((element.elementRef.clientWidth +
element.labelElementRef.clientWidth) /
- 2;
+ 2) *
+ ratio;
break;
}
}
+
return { x, y };
}
@@ -1196,12 +1240,14 @@ export default class VisualConsole {
width: 0,
height: 0,
lineWidth: this.props.relationLineWidth,
- color: notEmptyStringOr(child.props.colorStatus, "#CCC")
+ color: notEmptyStringOr(child.props.colorStatus, "#CCC"),
+ ratio: parent.props.ratio
}),
itemMetaDecoder({
receivedAt: new Date()
})
);
+
// Save a reference to the line item.
this.relations[identifier] = line;
diff --git a/visual_console_client/src/items/BasicChart.ts b/visual_console_client/src/items/BasicChart.ts
index ff475fc142..463a2dd57b 100644
--- a/visual_console_client/src/items/BasicChart.ts
+++ b/visual_console_client/src/items/BasicChart.ts
@@ -71,7 +71,7 @@ export default class BasicChart extends Item {
let value = "";
if (this.props.value !== null) {
- value = this.number_format(this.props.value, false, "", 2, 1000);
+ value = this.numberFormat(this.props.value, false, "", 2, 1000);
}
const moduleValue = document.createElement("h2");
@@ -131,7 +131,7 @@ export default class BasicChart extends Item {
let value = "";
if (this.props.value !== null) {
- value = this.number_format(this.props.value, false, "", 2, 1000);
+ value = this.numberFormat(this.props.value, false, "", 2, 1000);
}
const moduleValue = document.createElement("h2");
@@ -164,31 +164,31 @@ export default class BasicChart extends Item {
}
}
- protected number_format(
+ protected numberFormat(
number: number,
- force_integer: boolean,
+ forceInteger: boolean,
unit: string,
- short_data: number,
+ shortData: number,
divisor: number
) {
divisor = typeof divisor !== "undefined" ? divisor : 1000;
var decimals = 2;
- // Set maximum decimal precision to 99 in case short_data is not set.
- if (!short_data) {
- short_data = 99;
+ // Set maximum decimal precision to 99 in case shortData is not set.
+ if (!shortData) {
+ shortData = 99;
}
- if (force_integer) {
+ if (forceInteger) {
if (Math.round(number) != number) {
return "";
}
} else {
- short_data++;
- const aux_decimals = this.pad("1", short_data, 0);
+ shortData++;
+ const auxDecimals = this.pad("1", shortData, 0);
number =
- Math.round(number * Number.parseInt(aux_decimals)) /
- Number.parseInt(aux_decimals);
+ Math.round(number * Number.parseInt(auxDecimals)) /
+ Number.parseInt(auxDecimals);
}
var shorts = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];
diff --git a/visual_console_client/src/items/NetworkLink.ts b/visual_console_client/src/items/NetworkLink.ts
index d0feb6f813..42b19da6ea 100644
--- a/visual_console_client/src/items/NetworkLink.ts
+++ b/visual_console_client/src/items/NetworkLink.ts
@@ -100,6 +100,11 @@ export default class NetworkLink extends Line {
);
protected updateDomElement(element: HTMLElement): void {
+ if (this.itemProps.ratio != null) {
+ this.itemProps.x /= this.itemProps.ratio;
+ this.itemProps.y /= this.itemProps.ratio;
+ }
+
super.updateDomElement(element);
let {
@@ -119,6 +124,11 @@ export default class NetworkLink extends Line {
labelStartHeight
} = this.props;
+ if (this.itemProps.ratio != null) {
+ this.itemProps.x *= this.itemProps.ratio;
+ this.itemProps.y *= this.itemProps.ratio;
+ }
+
const svgs = element.getElementsByTagName("svg");
let line;
let svg;
diff --git a/visual_console_client/src/items/Odometer.ts b/visual_console_client/src/items/Odometer.ts
index 3de4e92e6c..a89d42d0ee 100644
--- a/visual_console_client/src/items/Odometer.ts
+++ b/visual_console_client/src/items/Odometer.ts
@@ -226,8 +226,8 @@ export default class Odometer extends Item {
script.onload = () => {
odometerB.style.transform = `rotate(${rotate}turn)`;
};
- var url_pandora = window.location.pathname.split("/")[1];
- script.src = `${document.dir}/${url_pandora}/include/javascript/pandora_alerts.js`;
+ var urlPandora = window.location.pathname.split("/")[1];
+ script.src = `${document.dir}/${urlPandora}/include/javascript/pandora_alerts.js`;
odometerA.appendChild(h1);
odometerA.appendChild(h2);
odometerContainer.appendChild(odometerB);
@@ -277,7 +277,7 @@ export default class Odometer extends Item {
/**
* To update the content element.
- * @override Item.updateDomElement
+ * @override resize
*/
public resize(width: number): void {
this.resizeElement(this.props.width);
diff --git a/visual_console_client/src/items/Percentile.ts b/visual_console_client/src/items/Percentile.ts
index ac87b13c31..f12a9e9582 100644
--- a/visual_console_client/src/items/Percentile.ts
+++ b/visual_console_client/src/items/Percentile.ts
@@ -286,7 +286,7 @@ export default class Percentile extends Item {
/**
* To update the content element.
- * @override Item.updateDomElement
+ * @override resizeElement
*/
public resizeElement(width: number, height: number): void {
if (this.props.percentileType === "progress-bar") {
@@ -298,7 +298,7 @@ export default class Percentile extends Item {
/**
* To update the content element.
- * @override Item.updateDomElement
+ * @override resize
*/
public resize(width: number): void {
this.resizeElement(width, width);
diff --git a/visual_console_client/src/main.css b/visual_console_client/src/main.css
index d1317c8a56..cd8b00e93f 100644
--- a/visual_console_client/src/main.css
+++ b/visual_console_client/src/main.css
@@ -32,6 +32,10 @@
.visual-console-item * {
overflow: visible;
font-family: inherit;
+ line-height: inherit;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
}
.visual-console-item.is-editing {
@@ -733,3 +737,8 @@ div.module-graph .gauge_d3_class {
height: 0px;
border: 2px solid #002f33;
}
+
+p {
+ margin-block-start: 1em;
+ margin-block-end: 1em;
+}