diff --git a/docker-compose.yml b/docker-compose.yml index fee16695..e874efe9 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,6 +33,7 @@ services: - ${DEV_LOCATION}/back/update_vendors.sh:/app/back/update_vendors.sh - ${DEV_LOCATION}/front/lib:/app/front/lib - ${DEV_LOCATION}/front/js:/app/front/js + - ${DEV_LOCATION}/front/report_templates:/front/report_templates - ${DEV_LOCATION}/install/start.debian.sh:/app/install/start.debian.sh - ${DEV_LOCATION}/install/user-mapping.debian.sh:/app/install/user-mapping.debian.sh - ${DEV_LOCATION}/install/install.debian.sh:/app/install/install.debian.sh diff --git a/front/css/app.css b/front/css/app.css index ba3dc1e6..b75f505a 100755 --- a/front/css/app.css +++ b/front/css/app.css @@ -742,7 +742,7 @@ height: 50px; { font-size: 20px; padding-top: 7px; - padding-bottom: 9px; + padding-bottom: 9px; } .overview-section .small-box .icon @@ -753,12 +753,12 @@ height: 50px; .overview-section { - border: solid; + /* border-top: solid; border-width: medium; border-width: medium; border-width: 1px; - border-radius: 15px; - margin-bottom: 3px; + border-radius: 15px; + margin-bottom: 3px; */ } @@ -771,6 +771,7 @@ height: 50px; font-size: 20px; padding-top: 7px; padding-bottom: 9px; + margin-left: -20px; } diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index cbfd1496..1da7163b 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -332,7 +332,7 @@ "HelpFAQ_Cat_Presence_401_head": "A device is displayed as present although it is \"Offline\".", "HelpFAQ_Cat_Presence_401_text": "If this happens, you have the possibility to delete the events for the device in question (details view). Another possibility would be to switch on the device and wait until NetAlertX recognizes the device as \"online\" with the next scan and then simply switch the device off again. Now NetAlertX should properly note the state of the device in the database with the next scan.", "HelpFAQ_Title": "Help / FAQ", - "LOADED_PLUGINS_description": "Which Plugins to load. Adding plugins might slow the application. Read more about which plugins need to be enabled, types, or scanning options in the plugins docs. Unloaded plugins will lose your settings. Only disabled plugins can be unloaded.", + "LOADED_PLUGINS_description": "Which Plugins to load. Adding plugins might slow the application. Read more about which plugins need to be enabled, types, or scanning options in the plugins docs. Unloaded plugins will lose your settings. Only disabled plugins can be unloaded.", "LOADED_PLUGINS_name": "Loaded plugins", "LOG_LEVEL_description": "This setting will enable more verbose logging. Useful for debugging events writing into the database.", "LOG_LEVEL_name": "Print additional logging", diff --git a/front/plugins/internet_ip/script.py b/front/plugins/internet_ip/script.py index adae2aa4..8a5d7693 100755 --- a/front/plugins/internet_ip/script.py +++ b/front/plugins/internet_ip/script.py @@ -51,7 +51,7 @@ def main(): # perform the new IP lookup N times specified by the INTRNT_TRIES setting new_internet_IP = "" INTRNT_RETRIES = get_setting_value("INTRNT_RETRIES") - tries_needed = 0 + retries_needed = 0 for i in range(INTRNT_RETRIES + 1): @@ -60,7 +60,7 @@ def main(): if new_internet_IP == no_internet_ip: time.sleep(1*i) # Exponential backoff strategy else: - tries_needed = i + retries_needed = i break plugin_objects = Plugin_Objects(RESULT_FILE) @@ -70,7 +70,7 @@ def main(): secondaryId = new_internet_IP, # IP Address watched1 = f'Previous IP: {PREV_IP}', watched2 = cmd_output.replace('\n',''), - watched3 = tries_needed, + watched3 = retries_needed, watched4 = '', extra = f'Previous IP: {PREV_IP}', foreignKey = 'Internet') diff --git a/front/plugins/notification_processing/config.json b/front/plugins/notification_processing/config.json index 1468ef99..71dee302 100755 --- a/front/plugins/notification_processing/config.json +++ b/front/plugins/notification_processing/config.json @@ -32,7 +32,7 @@ "function": "INCLUDED_SECTIONS", "type": "text.multiselect", "default_value": ["new_devices", "down_devices", "events"], - "options": ["new_devices", "down_devices", "events", "plugins"], + "options": ["new_devices", "down_devices", "down_reconnected", "events", "plugins"], "localized": ["name", "description"], "name": [ { diff --git a/front/report_templates/report_template.html b/front/report_templates/report_template.html index 10738da9..e7d75fc1 100755 --- a/front/report_templates/report_template.html +++ b/front/report_templates/report_template.html @@ -48,7 +48,8 @@ - + + diff --git a/front/report_templates/report_template.txt b/front/report_templates/report_template.txt index 80c9562c..ce814751 100755 --- a/front/report_templates/report_template.txt +++ b/front/report_templates/report_template.txt @@ -3,5 +3,6 @@ Server: + diff --git a/front/report_templates/report_template_new_version.html b/front/report_templates/report_template_new_version.html index c57dd4f6..5d4c60c2 100755 --- a/front/report_templates/report_template_new_version.html +++ b/front/report_templates/report_template_new_version.html @@ -53,6 +53,7 @@ + diff --git a/server/initialise.py b/server/initialise.py index 848d9d04..08da788e 100755 --- a/server/initialise.py +++ b/server/initialise.py @@ -137,7 +137,7 @@ def importConfigs (db, all_plugins): conf.TIMEZONE = ccd('TIMEZONE', 'Europe/Berlin' , c_d, 'Time zone', 'text', '', 'General') conf.PLUGINS_KEEP_HIST = ccd('PLUGINS_KEEP_HIST', 250 , c_d, 'Keep history entries', 'integer', '', 'General') conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'http://netalertx/' , c_d, 'NetAlertX URL', 'text', '', 'General') - conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', 'text.select', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish' ]", 'General') + conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', 'text.select', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian', 'Portuguese (Brazil)', 'Polish', 'Chinese (zh_cn)' ]", 'General') conf.UI_PRESENCE = ccd('UI_PRESENCE', ['online', 'offline', 'archived'] , c_d, 'Include in presence', 'text.multiselect', "['online', 'offline', 'archived']", 'General') conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', 'text.multiselect', "['Tile Cards', 'Device Presence']", 'General') conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', 'text.multiselect', "['online', 'offline', 'archived', 'new', 'down']", 'General') diff --git a/server/notification.py b/server/notification.py index e7362fbc..49c0c388 100755 --- a/server/notification.py +++ b/server/notification.py @@ -51,7 +51,7 @@ class Notification_obj: write_file (logPath + '/report_output.json', json.dumps(JSON)) # Check if nothing to report, end - if JSON["new_devices"] == [] and JSON["down_devices"] == [] and JSON["events"] == [] and JSON["plugins"] == []: + if JSON["new_devices"] == [] and JSON["down_devices"] == [] and JSON["events"] == [] and JSON["plugins"] == [] and JSON["down_reconnected"] == []: self.HasNotifications = False else: self.HasNotifications = True @@ -119,19 +119,35 @@ class Notification_obj: mail_html = mail_html.replace ('', BUILDFILE) # Start generating the TEXT & HTML notification messages + # new_devices + # --- html, text = construct_notifications(self.JSON, "new_devices") mail_text = mail_text.replace ('', text + '\n') mail_html = mail_html.replace ('', html) mylog('verbose', ['[Notification] New Devices sections done.']) + # down_devices + # --- html, text = construct_notifications(self.JSON, "down_devices") mail_text = mail_text.replace ('', text + '\n') mail_html = mail_html.replace ('', html) mylog('verbose', ['[Notification] Down Devices sections done.']) + + # down_reconnected + # --- + html, text = construct_notifications(self.JSON, "down_reconnected") + + mail_text = mail_text.replace ('', text + '\n') + mail_html = mail_html.replace ('', html) + mylog('verbose', ['[Notification] Reconnected Down Devices sections done.']) + + + # events + # --- html, text = construct_notifications(self.JSON, "events") @@ -140,6 +156,8 @@ class Notification_obj: mylog('verbose', ['[Notification] Events sections done.']) + # plugins + # --- html, text = construct_notifications(self.JSON, "plugins") mail_text = mail_text.replace ('', text + '\n') @@ -237,6 +255,21 @@ class Notification_obj: AND eve_DateTime < datetime('now', '-{get_setting_value('NTFPRCS_alert_down_time')} minutes', '{get_timezone_offset()}') """) + # Clear the pending email flag for reconnected devices + self.db.sql.execute(f"""UPDATE Events_Devices + SET eve_PendingAlertEmail = 0 + WHERE eve_MAC IN ( + SELECT down_events.eve_MAC + FROM Events_Devices AS down_events + INNER JOIN Events AS connected_events + ON connected_events.eve_MAC = down_events.eve_MAC + WHERE down_events.eve_EventType = 'Device Down' + AND connected_events.eve_EventType = 'Connected' + AND connected_events.eve_DateTime > down_events.eve_DateTime + ) + AND eve_EventType = 'Device Down' + """) + # clear plugin events self.db.sql.execute ("DELETE FROM Plugins_Events") diff --git a/server/reporting.py b/server/reporting.py index 727368f6..c02be0cd 100755 --- a/server/reporting.py +++ b/server/reporting.py @@ -37,6 +37,8 @@ def get_notifications (db): json_new_devices_meta = {} json_down_devices = [] json_down_devices_meta = {} + json_down_reconnected = [] + json_down_reconnected_meta = {} json_events = [] json_events_meta = {} json_plugins = [] @@ -72,7 +74,7 @@ def get_notifications (db): json_obj = db.get_table_as_json(sqlQuery) json_new_devices_meta = { - "title": "New devices", + "title": "πŸ†•New devices", "columnNames": json_obj.columnNames } @@ -100,11 +102,36 @@ def get_notifications (db): # Get the events as JSON json_obj = db.get_table_as_json(sqlQuery) - json_down_devices_meta = { - "title": "Down devices", + json_down_devices_meta = { + "title": "⚠ Down devices", "columnNames": json_obj.columnNames } json_down_devices = json_obj.json["data"] + + if 'down_reconnected' in sections: + # Compose Reconnected Down Section + # - select only Devices, that were previously down and now are Connected + sqlQuery = f""" + SELECT down_events.dev_Name, down_events.eve_MAC, down_events.dev_Vendor, down_events.eve_IP, + down_events.eve_DateTime AS DownTime, connected_events.eve_DateTime AS ConnectedTime + FROM Events_Devices AS down_events + INNER JOIN Events AS connected_events + ON connected_events.eve_MAC = down_events.eve_MAC + WHERE down_events.eve_EventType = 'Device Down' + AND connected_events.eve_EventType = 'Connected' + AND connected_events.eve_DateTime > down_events.eve_DateTime + AND down_events.eve_PendingAlertEmail = 1 + ORDER BY down_events.eve_DateTime; + """ + + # Get the events as JSON + json_obj = db.get_table_as_json(sqlQuery) + + json_down_reconnected_meta = { + "title": "πŸ” Reconnected down devices", + "columnNames": json_obj.columnNames + } + json_down_reconnected = json_obj.json["data"] if 'events' in sections: # Compose Events Section @@ -121,7 +148,7 @@ def get_notifications (db): json_obj = db.get_table_as_json(sqlQuery) json_events_meta = { - "title": "Events", + "title": "⚑ Events", "columnNames": json_obj.columnNames } json_events = json_obj.json["data"] @@ -134,7 +161,7 @@ def get_notifications (db): json_obj = db.get_table_as_json(sqlQuery) json_plugins_meta = { - "title": "Plugins", + "title": "πŸ”Œ Plugins", "columnNames": json_obj.columnNames } json_plugins = json_obj.json["data"] @@ -145,6 +172,8 @@ def get_notifications (db): "new_devices_meta": json_new_devices_meta, "down_devices": json_down_devices, "down_devices_meta": json_down_devices_meta, + "down_reconnected": json_down_reconnected, + "down_reconnected_meta": json_down_reconnected_meta, "events": json_events, "events_meta": json_events_meta, "plugins": json_plugins,