Merge pull request #1530 from netalertx/main

sync
This commit is contained in:
Jokob @NetAlertX
2026-02-22 14:21:47 +11:00
committed by GitHub
118 changed files with 3115 additions and 2797 deletions

View File

@@ -479,7 +479,12 @@ function setDeviceData(direction = '', refreshCallback = '') {
if (resp && resp.success) {
showMessage(getString("Device_Saved_Success"));
} else {
showMessage(getString("Device_Saved_Unexpected"));
console.log(resp);
errorMessage = resp?.error;
showMessage(`${getString("Device_Saved_Unexpected")}: ${errorMessage}`, 5000, "modal_red");
}
// Remove navigation prompt

View File

@@ -116,7 +116,7 @@ function initializeEventsDatatable (eventsRows) {
{
targets: [0],
'createdCell': function (td, cellData, rowData, row, col) {
$(td).html(translateHTMLcodes(localizeTimestamp(cellData)));
$(td).html(translateHTMLcodes((cellData)));
}
}
],

View File

@@ -12,7 +12,11 @@ var timerRefreshData = ''
var emptyArr = ['undefined', "", undefined, null, 'null'];
var UI_LANG = "English (en_us)";
const allLanguages = ["ar_ar","ca_ca","cs_cz","de_de","en_us","es_es","fa_fa","fr_fr","it_it","ja_jp","nb_no","pl_pl","pt_br","pt_pt","ru_ru","sv_sv","tr_tr","uk_ua","zh_cn"]; // needs to be same as in lang.php
const allLanguages = ["ar_ar","ca_ca","cs_cz","de_de",
"en_us","es_es","fa_fa","fr_fr",
"it_it","ja_jp","nb_no","pl_pl",
"pt_br","pt_pt","ru_ru","sv_sv",
"tr_tr","uk_ua","vi_vn","zh_cn"]; // needs to be same as in lang.php
var settingsJSON = {}
@@ -364,6 +368,9 @@ function getLangCode() {
case 'Ukrainian (uk_uk)':
lang_code = 'uk_ua';
break;
case 'Vietnamese (vi_vn)':
lang_code = 'vi_vn';
break;
}
return lang_code;
@@ -447,21 +454,36 @@ function localizeTimestamp(input) {
return formatSafe(input, tz);
function formatSafe(str, tz) {
const date = new Date(str);
// CHECK: Does the input string have timezone information?
// - Ends with Z: "2026-02-11T11:37:02Z"
// - Has GMT±offset: "Wed Feb 11 2026 12:34:12 GMT+1100 (...)"
// - Has offset at end: "2026-02-11 11:37:02+11:00"
// - Has timezone name in parentheses: "(Australian Eastern Daylight Time)"
const hasOffset = /Z$/i.test(str.trim()) ||
/GMT[+-]\d{2,4}/.test(str) ||
/[+-]\d{2}:?\d{2}$/.test(str.trim()) ||
/\([^)]+\)$/.test(str.trim());
// ⚠️ CRITICAL: All DB timestamps are stored in UTC without timezone markers.
// If no offset is present, we must explicitly mark it as UTC by appending 'Z'
// so JavaScript doesn't interpret it as local browser time.
let isoStr = str.trim();
if (!hasOffset) {
// Ensure proper ISO format before appending Z
// Replace space with 'T' if needed: "2026-02-11 11:37:02" → "2026-02-11T11:37:02Z"
isoStr = isoStr.trim().replace(/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})$/, '$1T$2') + 'Z';
}
const date = new Date(isoStr);
if (!isFinite(date)) {
console.error(`ERROR: Couldn't parse date: '${str}' with TIMEZONE ${tz}`);
return 'Failed conversion';
}
// CHECK: Does the input string have an offset (e.g., +11:00 or Z)?
// If it does, and we apply a 'tz' again, we double-shift.
const hasOffset = /[Z|[+-]\d{2}:?\d{2}]$/.test(str.trim());
return new Intl.DateTimeFormat(LOCALE, {
// If it has an offset, we display it as-is (UTC mode in Intl
// effectively means "don't add more hours").
// If no offset, apply your variable 'tz'.
timeZone: hasOffset ? 'UTC' : tz,
// Convert from UTC to user's configured timezone
timeZone: tz,
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hour12: false

File diff suppressed because one or more lines are too long

View File

View File

@@ -69,7 +69,8 @@
require 'php/templates/footer.php';
?>
<script src="lib/treeviz/bundle.js"></script>
<!-- <script src="lib/treeviz/bundle.js"></script> -->
<script src="lib/treeviz/treeviz.iife.js"></script>
<script defer>
@@ -388,7 +389,7 @@
const normalized_mac = node_mac.toLowerCase();
const sql = `
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort,
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort, devVlan,
CASE
WHEN devIsNew = 1 THEN 'New'
WHEN devPresentLastScan = 1 THEN 'On-line'
@@ -569,10 +570,10 @@ function getChildren(node, list, path, visited = [])
// Loop through all items to find children of the current node
for (var i in list) {
const item = list[i];
const parentMac = item.devParentMAC || ""; // null-safe
const nodeMac = node.devMac || ""; // null-safe
const parentMac = item.devParentMAC?.toLowerCase() || ""; // null-safe
const nodeMac = node.devMac?.toLowerCase() || ""; // null-safe
if (parentMac != "" && parentMac.toLowerCase() == nodeMac.toLowerCase() && !hiddenMacs.includes(parentMac)) {
if (parentMac != "" && parentMac == nodeMac && !hiddenMacs.includes(parentMac)) {
visibleNodesCount++;
@@ -588,6 +589,8 @@ function getChildren(node, list, path, visited = [])
parentNodesCount++;
}
// console.log(node);
return {
name: node.devName,
path: path,
@@ -607,6 +610,8 @@ function getChildren(node, list, path, visited = [])
alertDown: node.devAlertDown,
hasChildren: children.length > 0 || hiddenMacs.includes(node.devMac),
relType: node.devParentRelType,
devVlan: node.devVlan,
devSSID: node.devSSID,
hiddenChildren: hiddenMacs.includes(node.devMac),
qty: children.length,
children: children
@@ -649,6 +654,8 @@ function toggleSubTree(parentMac, treePath)
{
treePath = treePath.split('|')
parentMac = parentMac.toLowerCase()
if(!hiddenMacs.includes(parentMac))
{
hiddenMacs.push(parentMac)
@@ -883,6 +890,22 @@ function initTree(myHierarchy)
idKey: "mac",
hasFlatData: false,
relationnalField: "children",
linkLabel: {
render: (parent, child) => {
// Return text or HTML to display on the connection line
connectionLabel = (child?.data.devVlan ?? "") + "/" + (child?.data.devSSID ?? "");
if(connectionLabel == "/")
{
connectionLabel = "";
}
return connectionLabel;
// or with HTML:
// return "<tspan><strong>reports to</strong></tspan>";
},
color: "#336c87ff", // Label text color (optional)
fontSize: nodeHeightPx - 5 // Label font size in px (optional)
},
linkWidth: (nodeData) => 2,
linkColor: (nodeData) => {
relConf = getRelationshipConf(nodeData.data.relType)

View File

@@ -27,8 +27,8 @@ function initOnlineHistoryGraph() {
var archivedCounts = [];
res.data.forEach(function(entry) {
var dateObj = new Date(entry.Scan_Date);
var formattedTime = dateObj.toLocaleTimeString([], {hour: '2-digit', minute: '2-digit', hour12: false});
var formattedTime = localizeTimestamp(entry.Scan_Date).slice(11, 17);
timeStamps.push(formattedTime);
onlineCounts.push(entry.Online_Devices);

View File

@@ -789,4 +789,4 @@
"settings_system_label": "نظام",
"settings_update_item_warning": "قم بتحديث القيمة أدناه. احرص على اتباع التنسيق السابق. <b>لم يتم إجراء التحقق.</b>",
"test_event_tooltip": "احفظ التغييرات أولاً قبل اختبار الإعدادات."
}
}

View File

@@ -27,7 +27,7 @@
"AppEvents_ObjectType": "Object Type",
"AppEvents_Plugin": "Plugin",
"AppEvents_Type": "Type",
"BACKEND_API_URL_description": "Used to generate backend API URLs. Specify if you use reverse proxy to map to your <code>GRAPHQL_PORT</code>. Enter full URL starting with <code>http://</code> including the port number (no trailing slash <code>/</code>).",
"BACKEND_API_URL_description": "Used to allow the frontend to communicate with the backend. By default this is set to <code>/server</code> and generally should not be changed.",
"BACKEND_API_URL_name": "Backend API URL",
"BackDevDetail_Actions_Ask_Run": "Do you want to execute the action?",
"BackDevDetail_Actions_Not_Registered": "Action not registered: ",

View File

@@ -27,7 +27,7 @@
"AppEvents_ObjectType": "Type d'objet",
"AppEvents_Plugin": "Plugin",
"AppEvents_Type": "Type",
"BACKEND_API_URL_description": "Utilisé pour générer les URL de l'API back-end. Spécifiez si vous utiliser un reverse proxy pour mapper votre <code>GRAPHQL_PORT</code>. Renseigner l'URL complète, en commençant par <code>http://</code>, et en incluant le numéro de port (sans slash de fin <code>/</code>).",
"BACKEND_API_URL_description": "Utilisé pour autoriser l'interface utilisateur à communiquer avec le serveur. Par défaut, cela est défini sur <code>/serveur</code> et ne doit généralement pas être changé.",
"BACKEND_API_URL_name": "URL de l'API backend",
"BackDevDetail_Actions_Ask_Run": "Voulez-vous exécuter cette action?",
"BackDevDetail_Actions_Not_Registered": "Action non enregistrée: ",

View File

@@ -27,7 +27,7 @@
"AppEvents_ObjectType": "Tipo oggetto",
"AppEvents_Plugin": "Plugin",
"AppEvents_Type": "Tipo",
"BACKEND_API_URL_description": "Utilizzato per generare URL API backend. Specifica se utilizzi un proxy inverso per il mapping al tuo <code>GRAPHQL_PORT</code>. Inserisci l'URL completo che inizia con <code>http://</code> incluso il numero di porta (senza barra finale <code>/</code>).",
"BACKEND_API_URL_description": "Utilizzato per consentire al frontend di comunicare con il backend. Per impostazione predefinita è impostato su <code>/server</code> e generalmente non dovrebbe essere modificato.",
"BACKEND_API_URL_name": "URL API backend",
"BackDevDetail_Actions_Ask_Run": "Vuoi eseguire questa azione?",
"BackDevDetail_Actions_Not_Registered": "Azione non registrata: ",

View File

@@ -789,4 +789,4 @@
"settings_system_label": "システム",
"settings_update_item_warning": "以下の値を更新してください。以前のフォーマットに従うよう注意してください。<b>検証は行われません。</b>",
"test_event_tooltip": "設定をテストする前に、まず変更を保存してください。"
}
}

View File

@@ -5,15 +5,19 @@
// ###################################
$defaultLang = "en_us";
$allLanguages = [ "ar_ar", "ca_ca", "cs_cz", "de_de", "en_us", "es_es", "fa_fa", "fr_fr", "it_it", "ja_jp", "nb_no", "pl_pl", "pt_br", "pt_pt", "ru_ru", "sv_sv", "tr_tr", "uk_ua", "zh_cn"];
$allLanguages = [ "ar_ar", "ca_ca", "cs_cz", "de_de",
"en_us", "es_es", "fa_fa", "fr_fr",
"it_it", "ja_jp", "nb_no", "pl_pl",
"pt_br", "pt_pt", "ru_ru", "sv_sv",
"tr_tr", "uk_ua", "vi_vn", "zh_cn"];
global $db;
$result = $db->querySingle("SELECT setValue FROM Settings WHERE setKey = 'UI_LANG'");
$result = $db->querySingle("SELECT setValue FROM Settings WHERE setKey = 'UI_LANG'");
// below has to match exactly the values in /front/php/templates/language/lang.php & /front/js/common.js
switch($result){
switch($result){
case 'Arabic (ar_ar)': $pia_lang_selected = 'ar_ar'; break;
case 'Catalan (ca_ca)': $pia_lang_selected = 'ca_ca'; break;
case 'Czech (cs_cz)': $pia_lang_selected = 'cs_cz'; break;
@@ -32,6 +36,7 @@ switch($result){
case 'Swedish (sv_sv)': $pia_lang_selected = 'sv_sv'; break;
case 'Turkish (tr_tr)': $pia_lang_selected = 'tr_tr'; break;
case 'Ukrainian (uk_ua)': $pia_lang_selected = 'uk_ua'; break;
case 'Vietnamese (vi_vn)': $pia_lang_selected = 'vi_vn'; break;
case 'Chinese (zh_cn)': $pia_lang_selected = 'zh_cn'; break;
default: $pia_lang_selected = 'en_us'; break;
}

View File

@@ -38,6 +38,6 @@ if __name__ == "__main__":
json_files = ["en_us.json", "ar_ar.json", "ca_ca.json", "cs_cz.json", "de_de.json",
"es_es.json", "fa_fa.json", "fr_fr.json", "it_it.json", "ja_jp.json",
"nb_no.json", "pl_pl.json", "pt_br.json", "pt_pt.json", "ru_ru.json",
"sv_sv.json", "tr_tr.json", "uk_ua.json", "zh_cn.json"]
"sv_sv.json", "tr_tr.json", "vi_vn.json", "uk_ua.json", "zh_cn.json"]
file_paths = [os.path.join(current_path, file) for file in json_files]
merge_translations(file_paths[0], file_paths[1:])

View File

@@ -27,7 +27,7 @@
"AppEvents_ObjectType": "Тип объекта",
"AppEvents_Plugin": "Плагин",
"AppEvents_Type": "Тип",
"BACKEND_API_URL_description": "Используется для создания URL-адресов серверного API. Укажите, используете ли вы обратный прокси-сервер для сопоставления с вашим <code>GRAPHQL_PORT</code>. Введите полный URL-адрес, начинающийся с <code>http://</code>, включая номер порта (без косой черты <code>/</code>).",
"BACKEND_API_URL_description": "Используется для обеспечения связи между фронтендом и бэкендом. По умолчанию это значение установлено на <code>/server</code> и, как правило, не должно изменяться.",
"BACKEND_API_URL_name": "URL-адрес серверного API",
"BackDevDetail_Actions_Ask_Run": "Вы хотите выполнить действие?",
"BackDevDetail_Actions_Not_Registered": "Действие не зарегистрировано:· ",

View File

@@ -0,0 +1,792 @@
{
"API_CUSTOM_SQL_description": "",
"API_CUSTOM_SQL_name": "",
"API_TOKEN_description": "",
"API_TOKEN_name": "",
"API_display_name": "",
"API_icon": "",
"About_Design": "",
"About_Exit": "",
"About_Title": "",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "",
"AppEvents_Extra": "",
"AppEvents_GUID": "",
"AppEvents_Helper1": "",
"AppEvents_Helper2": "",
"AppEvents_Helper3": "",
"AppEvents_ObjectForeignKey": "",
"AppEvents_ObjectIndex": "",
"AppEvents_ObjectIsArchived": "",
"AppEvents_ObjectIsNew": "",
"AppEvents_ObjectPlugin": "",
"AppEvents_ObjectPrimaryID": "",
"AppEvents_ObjectSecondaryID": "",
"AppEvents_ObjectStatus": "",
"AppEvents_ObjectStatusColumn": "",
"AppEvents_ObjectType": "",
"AppEvents_Plugin": "",
"AppEvents_Type": "",
"BACKEND_API_URL_description": "",
"BACKEND_API_URL_name": "",
"BackDevDetail_Actions_Ask_Run": "",
"BackDevDetail_Actions_Not_Registered": "",
"BackDevDetail_Actions_Title_Run": "",
"BackDevDetail_Copy_Ask": "",
"BackDevDetail_Copy_Title": "",
"BackDevDetail_Tools_WOL_error": "",
"BackDevDetail_Tools_WOL_okay": "",
"BackDevices_Arpscan_disabled": "",
"BackDevices_Arpscan_enabled": "",
"BackDevices_Backup_CopError": "",
"BackDevices_Backup_Failed": "",
"BackDevices_Backup_okay": "",
"BackDevices_DBTools_DelDevError_a": "",
"BackDevices_DBTools_DelDevError_b": "",
"BackDevices_DBTools_DelDev_a": "",
"BackDevices_DBTools_DelDev_b": "",
"BackDevices_DBTools_DelEvents": "",
"BackDevices_DBTools_DelEventsError": "",
"BackDevices_DBTools_ImportCSV": "",
"BackDevices_DBTools_ImportCSVError": "",
"BackDevices_DBTools_ImportCSVMissing": "",
"BackDevices_DBTools_Purge": "",
"BackDevices_DBTools_UpdDev": "",
"BackDevices_DBTools_UpdDevError": "",
"BackDevices_DBTools_Upgrade": "",
"BackDevices_DBTools_UpgradeError": "",
"BackDevices_Device_UpdDevError": "",
"BackDevices_Restore_CopError": "",
"BackDevices_Restore_Failed": "",
"BackDevices_Restore_okay": "",
"BackDevices_darkmode_disabled": "",
"BackDevices_darkmode_enabled": "",
"CLEAR_NEW_FLAG_description": "",
"CLEAR_NEW_FLAG_name": "",
"CustProps_cant_remove": "",
"DAYS_TO_KEEP_EVENTS_description": "",
"DAYS_TO_KEEP_EVENTS_name": "",
"DISCOVER_PLUGINS_description": "",
"DISCOVER_PLUGINS_name": "",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "",
"DevDetail_Copy_Device_Tooltip": "",
"DevDetail_CustomProperties_Title": "",
"DevDetail_CustomProps_reset_info": "",
"DevDetail_DisplayFields_Title": "",
"DevDetail_EveandAl_AlertAllEvents": "",
"DevDetail_EveandAl_AlertDown": "",
"DevDetail_EveandAl_Archived": "",
"DevDetail_EveandAl_NewDevice": "",
"DevDetail_EveandAl_NewDevice_Tooltip": "",
"DevDetail_EveandAl_RandomMAC": "",
"DevDetail_EveandAl_ScanCycle": "",
"DevDetail_EveandAl_ScanCycle_a": "",
"DevDetail_EveandAl_ScanCycle_z": "",
"DevDetail_EveandAl_Skip": "",
"DevDetail_EveandAl_Title": "",
"DevDetail_Events_CheckBox": "",
"DevDetail_GoToNetworkNode": "",
"DevDetail_Icon": "",
"DevDetail_Icon_Descr": "",
"DevDetail_Loading": "",
"DevDetail_MainInfo_Comments": "",
"DevDetail_MainInfo_Favorite": "",
"DevDetail_MainInfo_Group": "",
"DevDetail_MainInfo_Location": "",
"DevDetail_MainInfo_Name": "",
"DevDetail_MainInfo_Network": "",
"DevDetail_MainInfo_Network_Port": "",
"DevDetail_MainInfo_Network_Site": "",
"DevDetail_MainInfo_Network_Title": "",
"DevDetail_MainInfo_Owner": "",
"DevDetail_MainInfo_SSID": "",
"DevDetail_MainInfo_Title": "",
"DevDetail_MainInfo_Type": "",
"DevDetail_MainInfo_Vendor": "",
"DevDetail_MainInfo_mac": "",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "",
"DevDetail_Network_Port_hover": "",
"DevDetail_Nmap_Scans": "",
"DevDetail_Nmap_Scans_desc": "",
"DevDetail_Nmap_buttonDefault": "",
"DevDetail_Nmap_buttonDefault_text": "",
"DevDetail_Nmap_buttonDetail": "",
"DevDetail_Nmap_buttonDetail_text": "",
"DevDetail_Nmap_buttonFast": "",
"DevDetail_Nmap_buttonFast_text": "",
"DevDetail_Nmap_buttonSkipDiscovery": "",
"DevDetail_Nmap_buttonSkipDiscovery_text": "",
"DevDetail_Nmap_resultsLink": "",
"DevDetail_Owner_hover": "",
"DevDetail_Periodselect_All": "",
"DevDetail_Periodselect_LastMonth": "",
"DevDetail_Periodselect_LastWeek": "",
"DevDetail_Periodselect_LastYear": "",
"DevDetail_Periodselect_today": "",
"DevDetail_Run_Actions_Title": "",
"DevDetail_Run_Actions_Tooltip": "",
"DevDetail_SessionInfo_FirstSession": "",
"DevDetail_SessionInfo_LastIP": "",
"DevDetail_SessionInfo_LastSession": "",
"DevDetail_SessionInfo_StaticIP": "",
"DevDetail_SessionInfo_Status": "",
"DevDetail_SessionInfo_Title": "",
"DevDetail_SessionTable_Additionalinfo": "",
"DevDetail_SessionTable_Connection": "",
"DevDetail_SessionTable_Disconnection": "",
"DevDetail_SessionTable_Duration": "",
"DevDetail_SessionTable_IP": "",
"DevDetail_SessionTable_Order": "",
"DevDetail_Shortcut_CurrentStatus": "",
"DevDetail_Shortcut_DownAlerts": "",
"DevDetail_Shortcut_Presence": "",
"DevDetail_Shortcut_Sessions": "",
"DevDetail_Tab_Details": "",
"DevDetail_Tab_Events": "",
"DevDetail_Tab_EventsTableDate": "",
"DevDetail_Tab_EventsTableEvent": "",
"DevDetail_Tab_EventsTableIP": "",
"DevDetail_Tab_EventsTableInfo": "",
"DevDetail_Tab_Nmap": "",
"DevDetail_Tab_NmapEmpty": "",
"DevDetail_Tab_NmapTableExtra": "",
"DevDetail_Tab_NmapTableHeader": "",
"DevDetail_Tab_NmapTableIndex": "",
"DevDetail_Tab_NmapTablePort": "",
"DevDetail_Tab_NmapTableService": "",
"DevDetail_Tab_NmapTableState": "",
"DevDetail_Tab_NmapTableText": "",
"DevDetail_Tab_NmapTableTime": "",
"DevDetail_Tab_Plugins": "",
"DevDetail_Tab_Presence": "",
"DevDetail_Tab_Sessions": "",
"DevDetail_Tab_Tools": "",
"DevDetail_Tab_Tools_Internet_Info_Description": "",
"DevDetail_Tab_Tools_Internet_Info_Error": "",
"DevDetail_Tab_Tools_Internet_Info_Start": "",
"DevDetail_Tab_Tools_Internet_Info_Title": "",
"DevDetail_Tab_Tools_Nslookup_Description": "",
"DevDetail_Tab_Tools_Nslookup_Error": "",
"DevDetail_Tab_Tools_Nslookup_Start": "",
"DevDetail_Tab_Tools_Nslookup_Title": "",
"DevDetail_Tab_Tools_Speedtest_Description": "",
"DevDetail_Tab_Tools_Speedtest_Start": "",
"DevDetail_Tab_Tools_Speedtest_Title": "",
"DevDetail_Tab_Tools_Traceroute_Description": "",
"DevDetail_Tab_Tools_Traceroute_Error": "",
"DevDetail_Tab_Tools_Traceroute_Start": "",
"DevDetail_Tab_Tools_Traceroute_Title": "",
"DevDetail_Tools_WOL": "",
"DevDetail_Tools_WOL_noti": "",
"DevDetail_Tools_WOL_noti_text": "",
"DevDetail_Type_hover": "",
"DevDetail_Vendor_hover": "",
"DevDetail_WOL_Title": "",
"DevDetail_button_AddIcon": "",
"DevDetail_button_AddIcon_Help": "",
"DevDetail_button_AddIcon_Tooltip": "",
"DevDetail_button_Delete": "",
"DevDetail_button_DeleteEvents": "",
"DevDetail_button_DeleteEvents_Warning": "",
"DevDetail_button_Delete_ask": "",
"DevDetail_button_OverwriteIcons": "",
"DevDetail_button_OverwriteIcons_Tooltip": "",
"DevDetail_button_OverwriteIcons_Warning": "",
"DevDetail_button_Reset": "",
"DevDetail_button_Save": "",
"DeviceEdit_ValidMacIp": "",
"Device_MultiEdit": "",
"Device_MultiEdit_Backup": "",
"Device_MultiEdit_Fields": "",
"Device_MultiEdit_MassActions": "",
"Device_MultiEdit_No_Devices": "",
"Device_MultiEdit_Tooltip": "",
"Device_Save_Failed": "",
"Device_Save_Unauthorized": "",
"Device_Saved_Success": "",
"Device_Saved_Unexpected": "",
"Device_Searchbox": "",
"Device_Shortcut_AllDevices": "",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "",
"Device_Shortcut_Connected": "",
"Device_Shortcut_Devices": "",
"Device_Shortcut_DownAlerts": "",
"Device_Shortcut_DownOnly": "",
"Device_Shortcut_Favorites": "",
"Device_Shortcut_NewDevices": "",
"Device_Shortcut_OnlineChart": "",
"Device_TableHead_AlertDown": "",
"Device_TableHead_Connected_Devices": "",
"Device_TableHead_CustomProps": "",
"Device_TableHead_FQDN": "",
"Device_TableHead_Favorite": "",
"Device_TableHead_FirstSession": "",
"Device_TableHead_GUID": "",
"Device_TableHead_Group": "",
"Device_TableHead_IPv4": "",
"Device_TableHead_IPv6": "",
"Device_TableHead_Icon": "",
"Device_TableHead_LastIP": "",
"Device_TableHead_LastIPOrder": "",
"Device_TableHead_LastSession": "",
"Device_TableHead_Location": "",
"Device_TableHead_MAC": "",
"Device_TableHead_MAC_full": "",
"Device_TableHead_Name": "",
"Device_TableHead_NetworkSite": "",
"Device_TableHead_Owner": "",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "",
"Device_TableHead_Port": "",
"Device_TableHead_PresentLastScan": "",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "",
"Device_TableHead_Rowid": "",
"Device_TableHead_SSID": "",
"Device_TableHead_SourcePlugin": "",
"Device_TableHead_Status": "",
"Device_TableHead_SyncHubNodeName": "",
"Device_TableHead_Type": "",
"Device_TableHead_Vendor": "",
"Device_TableHead_Vlan": "",
"Device_Table_Not_Network_Device": "",
"Device_Table_info": "",
"Device_Table_nav_next": "",
"Device_Table_nav_prev": "",
"Device_Tablelenght": "",
"Device_Tablelenght_all": "",
"Device_Title": "",
"Devices_Filters": "",
"ENABLE_PLUGINS_description": "",
"ENABLE_PLUGINS_name": "",
"ENCRYPTION_KEY_description": "",
"ENCRYPTION_KEY_name": "",
"Email_display_name": "",
"Email_icon": "",
"Events_Loading": "",
"Events_Periodselect_All": "",
"Events_Periodselect_LastMonth": "",
"Events_Periodselect_LastWeek": "",
"Events_Periodselect_LastYear": "",
"Events_Periodselect_today": "",
"Events_Searchbox": "",
"Events_Shortcut_AllEvents": "",
"Events_Shortcut_DownAlerts": "",
"Events_Shortcut_Events": "",
"Events_Shortcut_MissSessions": "",
"Events_Shortcut_NewDevices": "",
"Events_Shortcut_Sessions": "",
"Events_Shortcut_VoidSessions": "",
"Events_TableHead_AdditionalInfo": "",
"Events_TableHead_Connection": "",
"Events_TableHead_Date": "",
"Events_TableHead_Device": "",
"Events_TableHead_Disconnection": "",
"Events_TableHead_Duration": "",
"Events_TableHead_DurationOrder": "",
"Events_TableHead_EventType": "",
"Events_TableHead_IP": "",
"Events_TableHead_IPOrder": "",
"Events_TableHead_Order": "",
"Events_TableHead_Owner": "",
"Events_TableHead_PendingAlert": "",
"Events_Table_info": "",
"Events_Table_nav_next": "",
"Events_Table_nav_prev": "",
"Events_Tablelenght": "",
"Events_Tablelenght_all": "",
"Events_Title": "",
"FakeMAC_hover": "",
"FieldLock_Error": "",
"FieldLock_Lock_Tooltip": "",
"FieldLock_Locked": "",
"FieldLock_SaveBeforeLocking": "",
"FieldLock_Source_Label": "",
"FieldLock_Unlock_Tooltip": "",
"FieldLock_Unlocked": "",
"GRAPHQL_PORT_description": "",
"GRAPHQL_PORT_name": "",
"Gen_Action": "",
"Gen_Add": "",
"Gen_AddDevice": "",
"Gen_Add_All": "",
"Gen_All_Devices": "",
"Gen_AreYouSure": "",
"Gen_Backup": "",
"Gen_Cancel": "",
"Gen_Change": "",
"Gen_Copy": "",
"Gen_CopyToClipboard": "",
"Gen_DataUpdatedUITakesTime": "",
"Gen_Delete": "",
"Gen_DeleteAll": "",
"Gen_Description": "",
"Gen_Error": "",
"Gen_Filter": "",
"Gen_Generate": "",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
"Gen_LockedDB": "",
"Gen_NetworkMask": "",
"Gen_Offline": "",
"Gen_Okay": "",
"Gen_Online": "",
"Gen_Purge": "",
"Gen_ReadDocs": "",
"Gen_Remove_All": "",
"Gen_Remove_Last": "",
"Gen_Reset": "",
"Gen_Restore": "",
"Gen_Run": "",
"Gen_Save": "",
"Gen_Saved": "",
"Gen_Search": "",
"Gen_Select": "",
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "",
"Gen_Subnet": "",
"Gen_Switch": "",
"Gen_Upd": "",
"Gen_Upd_Fail": "",
"Gen_Update": "",
"Gen_Update_Value": "",
"Gen_ValidIcon": "",
"Gen_Warning": "",
"Gen_Work_In_Progress": "",
"Gen_create_new_device": "",
"Gen_create_new_device_info": "",
"General_display_name": "",
"General_icon": "",
"HRS_TO_KEEP_NEWDEV_description": "",
"HRS_TO_KEEP_NEWDEV_name": "",
"HRS_TO_KEEP_OFFDEV_description": "",
"HRS_TO_KEEP_OFFDEV_name": "",
"LOADED_PLUGINS_description": "",
"LOADED_PLUGINS_name": "",
"LOG_LEVEL_description": "",
"LOG_LEVEL_name": "",
"Loading": "",
"Login_Box": "",
"Login_Default_PWD": "",
"Login_Info": "",
"Login_Psw-box": "",
"Login_Psw_alert": "",
"Login_Psw_folder": "",
"Login_Psw_new": "",
"Login_Psw_run": "",
"Login_Remember": "",
"Login_Remember_small": "",
"Login_Submit": "",
"Login_Toggle_Alert_headline": "",
"Login_Toggle_Info": "",
"Login_Toggle_Info_headline": "",
"Maint_PurgeLog": "",
"Maint_RestartServer": "",
"Maint_Restart_Server_noti_text": "",
"Maintenance_InitCheck": "",
"Maintenance_InitCheck_Checking": "",
"Maintenance_InitCheck_QuickSetupGuide": "",
"Maintenance_InitCheck_Success": "",
"Maintenance_ReCheck": "",
"Maintenance_Running_Version": "",
"Maintenance_Status": "",
"Maintenance_Title": "",
"Maintenance_Tool_DownloadConfig": "",
"Maintenance_Tool_DownloadConfig_text": "",
"Maintenance_Tool_DownloadWorkflows": "",
"Maintenance_Tool_DownloadWorkflows_text": "",
"Maintenance_Tool_ExportCSV": "",
"Maintenance_Tool_ExportCSV_noti": "",
"Maintenance_Tool_ExportCSV_noti_text": "",
"Maintenance_Tool_ExportCSV_text": "",
"Maintenance_Tool_ImportCSV": "",
"Maintenance_Tool_ImportCSV_noti": "",
"Maintenance_Tool_ImportCSV_noti_text": "",
"Maintenance_Tool_ImportCSV_text": "",
"Maintenance_Tool_ImportConfig_noti": "",
"Maintenance_Tool_ImportPastedCSV": "",
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
"Maintenance_Tool_ImportPastedCSV_text": "",
"Maintenance_Tool_ImportPastedConfig": "",
"Maintenance_Tool_ImportPastedConfig_noti_text": "",
"Maintenance_Tool_ImportPastedConfig_text": "",
"Maintenance_Tool_UnlockFields": "",
"Maintenance_Tool_UnlockFields_noti": "",
"Maintenance_Tool_UnlockFields_noti_text": "",
"Maintenance_Tool_UnlockFields_text": "",
"Maintenance_Tool_arpscansw": "",
"Maintenance_Tool_arpscansw_noti": "",
"Maintenance_Tool_arpscansw_noti_text": "",
"Maintenance_Tool_arpscansw_text": "",
"Maintenance_Tool_backup": "",
"Maintenance_Tool_backup_noti": "",
"Maintenance_Tool_backup_noti_text": "",
"Maintenance_Tool_backup_text": "",
"Maintenance_Tool_check_visible": "",
"Maintenance_Tool_clearSourceFields_selected": "",
"Maintenance_Tool_clearSourceFields_selected_noti": "",
"Maintenance_Tool_clearSourceFields_selected_text": "",
"Maintenance_Tool_darkmode": "",
"Maintenance_Tool_darkmode_noti": "",
"Maintenance_Tool_darkmode_noti_text": "",
"Maintenance_Tool_darkmode_text": "",
"Maintenance_Tool_del_ActHistory": "",
"Maintenance_Tool_del_ActHistory_noti": "",
"Maintenance_Tool_del_ActHistory_noti_text": "",
"Maintenance_Tool_del_ActHistory_text": "",
"Maintenance_Tool_del_alldev": "",
"Maintenance_Tool_del_alldev_noti": "",
"Maintenance_Tool_del_alldev_noti_text": "",
"Maintenance_Tool_del_alldev_text": "",
"Maintenance_Tool_del_allevents": "",
"Maintenance_Tool_del_allevents30": "",
"Maintenance_Tool_del_allevents30_noti": "",
"Maintenance_Tool_del_allevents30_noti_text": "",
"Maintenance_Tool_del_allevents30_text": "",
"Maintenance_Tool_del_allevents_noti": "",
"Maintenance_Tool_del_allevents_noti_text": "",
"Maintenance_Tool_del_allevents_text": "",
"Maintenance_Tool_del_empty_macs": "",
"Maintenance_Tool_del_empty_macs_noti": "",
"Maintenance_Tool_del_empty_macs_noti_text": "",
"Maintenance_Tool_del_empty_macs_text": "",
"Maintenance_Tool_del_selecteddev": "",
"Maintenance_Tool_del_selecteddev_text": "",
"Maintenance_Tool_del_unknowndev": "",
"Maintenance_Tool_del_unknowndev_noti": "",
"Maintenance_Tool_del_unknowndev_noti_text": "",
"Maintenance_Tool_del_unknowndev_text": "",
"Maintenance_Tool_del_unlockFields_selecteddev_text": "",
"Maintenance_Tool_displayed_columns_text": "",
"Maintenance_Tool_drag_me": "",
"Maintenance_Tool_order_columns_text": "",
"Maintenance_Tool_purgebackup": "",
"Maintenance_Tool_purgebackup_noti": "",
"Maintenance_Tool_purgebackup_noti_text": "",
"Maintenance_Tool_purgebackup_text": "",
"Maintenance_Tool_restore": "",
"Maintenance_Tool_restore_noti": "",
"Maintenance_Tool_restore_noti_text": "",
"Maintenance_Tool_restore_text": "",
"Maintenance_Tool_unlockFields_selecteddev": "",
"Maintenance_Tool_unlockFields_selecteddev_noti": "",
"Maintenance_Tool_upgrade_database_noti": "",
"Maintenance_Tool_upgrade_database_noti_text": "",
"Maintenance_Tool_upgrade_database_text": "",
"Maintenance_Tools_Tab_BackupRestore": "",
"Maintenance_Tools_Tab_Logging": "",
"Maintenance_Tools_Tab_Settings": "",
"Maintenance_Tools_Tab_Tools": "",
"Maintenance_Tools_Tab_UISettings": "",
"Maintenance_arp_status": "",
"Maintenance_arp_status_off": "",
"Maintenance_arp_status_on": "",
"Maintenance_built_on": "",
"Maintenance_current_version": "",
"Maintenance_database_backup": "",
"Maintenance_database_backup_found": "",
"Maintenance_database_backup_total": "",
"Maintenance_database_lastmod": "",
"Maintenance_database_path": "",
"Maintenance_database_rows": "",
"Maintenance_database_size": "",
"Maintenance_lang_selector_apply": "",
"Maintenance_lang_selector_empty": "",
"Maintenance_lang_selector_lable": "",
"Maintenance_lang_selector_text": "",
"Maintenance_new_version": "",
"Maintenance_themeselector_apply": "",
"Maintenance_themeselector_empty": "",
"Maintenance_themeselector_lable": "",
"Maintenance_themeselector_text": "",
"Maintenance_version": "",
"NETWORK_DEVICE_TYPES_description": "",
"NETWORK_DEVICE_TYPES_name": "",
"Navigation_About": "",
"Navigation_AppEvents": "",
"Navigation_Devices": "",
"Navigation_Donations": "",
"Navigation_Events": "",
"Navigation_Integrations": "",
"Navigation_Maintenance": "",
"Navigation_Monitoring": "",
"Navigation_Network": "",
"Navigation_Notifications": "",
"Navigation_Plugins": "",
"Navigation_Presence": "",
"Navigation_Report": "",
"Navigation_Settings": "",
"Navigation_SystemInfo": "",
"Navigation_Workflows": "",
"Network_Assign": "",
"Network_Cant_Assign": "",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "",
"Network_Connected": "",
"Network_Devices": "",
"Network_ManageAdd": "",
"Network_ManageAdd_Name": "",
"Network_ManageAdd_Name_text": "",
"Network_ManageAdd_Port": "",
"Network_ManageAdd_Port_text": "",
"Network_ManageAdd_Submit": "",
"Network_ManageAdd_Type": "",
"Network_ManageAdd_Type_text": "",
"Network_ManageAssign": "",
"Network_ManageDel": "",
"Network_ManageDel_Name": "",
"Network_ManageDel_Name_text": "",
"Network_ManageDel_Submit": "",
"Network_ManageDevices": "",
"Network_ManageEdit": "",
"Network_ManageEdit_ID": "",
"Network_ManageEdit_ID_text": "",
"Network_ManageEdit_Name": "",
"Network_ManageEdit_Name_text": "",
"Network_ManageEdit_Port": "",
"Network_ManageEdit_Port_text": "",
"Network_ManageEdit_Submit": "",
"Network_ManageEdit_Type": "",
"Network_ManageEdit_Type_text": "",
"Network_ManageLeaf": "",
"Network_ManageUnassign": "",
"Network_NoAssignedDevices": "",
"Network_NoDevices": "",
"Network_Node": "",
"Network_Node_Name": "",
"Network_Parent": "",
"Network_Root": "",
"Network_Root_Not_Configured": "",
"Network_Root_Unconfigurable": "",
"Network_ShowArchived": "",
"Network_ShowOffline": "",
"Network_Table_Hostname": "",
"Network_Table_IP": "",
"Network_Table_State": "",
"Network_Title": "",
"Network_UnassignedDevices": "",
"Notifications_All": "",
"Notifications_Mark_All_Read": "",
"PIALERT_WEB_PASSWORD_description": "",
"PIALERT_WEB_PASSWORD_name": "",
"PIALERT_WEB_PROTECTION_description": "",
"PIALERT_WEB_PROTECTION_name": "",
"PLUGINS_KEEP_HIST_description": "",
"PLUGINS_KEEP_HIST_name": "",
"Plugins_DeleteAll": "",
"Plugins_Filters_Mac": "",
"Plugins_History": "",
"Plugins_Obj_DeleteListed": "",
"Plugins_Objects": "",
"Plugins_Out_of": "",
"Plugins_Unprocessed_Events": "",
"Plugins_no_control": "",
"Presence_CalHead_day": "",
"Presence_CalHead_lang": "",
"Presence_CalHead_month": "",
"Presence_CalHead_quarter": "",
"Presence_CalHead_week": "",
"Presence_CalHead_year": "",
"Presence_CallHead_Devices": "",
"Presence_Key_OnlineNow": "",
"Presence_Key_OnlineNow_desc": "",
"Presence_Key_OnlinePast": "",
"Presence_Key_OnlinePastMiss": "",
"Presence_Key_OnlinePastMiss_desc": "",
"Presence_Key_OnlinePast_desc": "",
"Presence_Loading": "",
"Presence_Shortcut_AllDevices": "",
"Presence_Shortcut_Archived": "",
"Presence_Shortcut_Connected": "",
"Presence_Shortcut_Devices": "",
"Presence_Shortcut_DownAlerts": "",
"Presence_Shortcut_Favorites": "",
"Presence_Shortcut_NewDevices": "",
"Presence_Title": "",
"REFRESH_FQDN_description": "",
"REFRESH_FQDN_name": "",
"REPORT_DASHBOARD_URL_description": "",
"REPORT_DASHBOARD_URL_name": "",
"REPORT_ERROR": "",
"REPORT_MAIL_description": "",
"REPORT_MAIL_name": "",
"REPORT_TITLE": "",
"RandomMAC_hover": "",
"Reports_Sent_Log": "",
"SCAN_SUBNETS_description": "",
"SCAN_SUBNETS_name": "",
"SYSTEM_TITLE": "",
"Setting_Override": "",
"Setting_Override_Description": "",
"Settings_Metadata_Toggle": "",
"Settings_Show_Description": "",
"Settings_device_Scanners_desync": "",
"Settings_device_Scanners_desync_popup": "",
"Speedtest_Results": "",
"Systeminfo_AvailableIps": "",
"Systeminfo_CPU": "",
"Systeminfo_CPU_Cores": "",
"Systeminfo_CPU_Name": "",
"Systeminfo_CPU_Speed": "",
"Systeminfo_CPU_Temp": "",
"Systeminfo_CPU_Vendor": "",
"Systeminfo_Client_Resolution": "",
"Systeminfo_Client_User_Agent": "",
"Systeminfo_General": "",
"Systeminfo_General_Date": "",
"Systeminfo_General_Date2": "",
"Systeminfo_General_Full_Date": "",
"Systeminfo_General_TimeZone": "",
"Systeminfo_Memory": "",
"Systeminfo_Memory_Total_Memory": "",
"Systeminfo_Memory_Usage": "",
"Systeminfo_Memory_Usage_Percent": "",
"Systeminfo_Motherboard": "",
"Systeminfo_Motherboard_BIOS": "",
"Systeminfo_Motherboard_BIOS_Date": "",
"Systeminfo_Motherboard_BIOS_Vendor": "",
"Systeminfo_Motherboard_Manufactured": "",
"Systeminfo_Motherboard_Name": "",
"Systeminfo_Motherboard_Revision": "",
"Systeminfo_Network": "",
"Systeminfo_Network_Accept_Encoding": "",
"Systeminfo_Network_Accept_Language": "",
"Systeminfo_Network_Connection_Port": "",
"Systeminfo_Network_HTTP_Host": "",
"Systeminfo_Network_HTTP_Referer": "",
"Systeminfo_Network_HTTP_Referer_String": "",
"Systeminfo_Network_Hardware": "",
"Systeminfo_Network_Hardware_Interface_Mask": "",
"Systeminfo_Network_Hardware_Interface_Name": "",
"Systeminfo_Network_Hardware_Interface_RX": "",
"Systeminfo_Network_Hardware_Interface_TX": "",
"Systeminfo_Network_IP": "",
"Systeminfo_Network_IP_Connection": "",
"Systeminfo_Network_IP_Server": "",
"Systeminfo_Network_MIME": "",
"Systeminfo_Network_Request_Method": "",
"Systeminfo_Network_Request_Time": "",
"Systeminfo_Network_Request_URI": "",
"Systeminfo_Network_Secure_Connection": "",
"Systeminfo_Network_Secure_Connection_String": "",
"Systeminfo_Network_Server_Name": "",
"Systeminfo_Network_Server_Name_String": "",
"Systeminfo_Network_Server_Query": "",
"Systeminfo_Network_Server_Query_String": "",
"Systeminfo_Network_Server_Version": "",
"Systeminfo_Services": "",
"Systeminfo_Services_Description": "",
"Systeminfo_Services_Name": "",
"Systeminfo_Storage": "",
"Systeminfo_Storage_Device": "",
"Systeminfo_Storage_Mount": "",
"Systeminfo_Storage_Size": "",
"Systeminfo_Storage_Type": "",
"Systeminfo_Storage_Usage": "",
"Systeminfo_Storage_Usage_Free": "",
"Systeminfo_Storage_Usage_Mount": "",
"Systeminfo_Storage_Usage_Total": "",
"Systeminfo_Storage_Usage_Used": "",
"Systeminfo_System": "",
"Systeminfo_System_AVG": "",
"Systeminfo_System_Architecture": "",
"Systeminfo_System_Kernel": "",
"Systeminfo_System_OSVersion": "",
"Systeminfo_System_Running_Processes": "",
"Systeminfo_System_System": "",
"Systeminfo_System_Uname": "",
"Systeminfo_System_Uptime": "",
"Systeminfo_This_Client": "",
"Systeminfo_USB_Devices": "",
"TICKER_MIGRATE_TO_NETALERTX": "",
"TIMEZONE_description": "",
"TIMEZONE_name": "",
"UI_DEV_SECTIONS_description": "",
"UI_DEV_SECTIONS_name": "",
"UI_ICONS_description": "",
"UI_ICONS_name": "",
"UI_LANG_description": "",
"UI_LANG_name": "",
"UI_MY_DEVICES_description": "",
"UI_MY_DEVICES_name": "",
"UI_NOT_RANDOM_MAC_description": "",
"UI_NOT_RANDOM_MAC_name": "",
"UI_PRESENCE_description": "",
"UI_PRESENCE_name": "",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"VERSION_description": "",
"VERSION_name": "",
"WF_Action_Add": "",
"WF_Action_field": "",
"WF_Action_type": "",
"WF_Action_value": "",
"WF_Actions": "",
"WF_Add": "",
"WF_Add_Condition": "",
"WF_Add_Group": "",
"WF_Condition_field": "",
"WF_Condition_operator": "",
"WF_Condition_value": "",
"WF_Conditions": "",
"WF_Conditions_logic_rules": "",
"WF_Duplicate": "",
"WF_Enabled": "",
"WF_Export": "",
"WF_Export_Copy": "",
"WF_Import": "",
"WF_Import_Copy": "",
"WF_Name": "",
"WF_Remove": "",
"WF_Remove_Copy": "",
"WF_Save": "",
"WF_Trigger": "",
"WF_Trigger_event_type": "",
"WF_Trigger_type": "",
"add_icon_event_tooltip": "",
"add_option_event_tooltip": "",
"copy_icons_event_tooltip": "",
"devices_old": "",
"general_event_description": "",
"general_event_title": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "",
"new_version_available": "",
"report_guid": "",
"report_guid_missing": "",
"report_select_format": "",
"report_time": "",
"run_event_tooltip": "",
"select_icon_event_tooltip": "",
"settings_core_icon": "",
"settings_core_label": "",
"settings_device_scanners": "",
"settings_device_scanners_icon": "",
"settings_device_scanners_info": "",
"settings_device_scanners_label": "",
"settings_enabled": "",
"settings_enabled_icon": "",
"settings_expand_all": "",
"settings_imported": "",
"settings_imported_label": "",
"settings_missing": "",
"settings_missing_block": "",
"settings_old": "",
"settings_other_scanners": "",
"settings_other_scanners_icon": "",
"settings_other_scanners_label": "",
"settings_publishers": "",
"settings_publishers_icon": "",
"settings_publishers_info": "",
"settings_publishers_label": "",
"settings_readonly": "",
"settings_saved": "",
"settings_system_icon": "",
"settings_system_label": "",
"settings_update_item_warning": "",
"test_event_tooltip": ""
}

View File

@@ -11,7 +11,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
import conf # noqa: E402 [flake8 lint suppression]
from const import confFileName, logPath # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
@@ -60,7 +60,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId = pluginName,
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = notification["GUID"],
watched2 = result,
watched3 = 'null',

View File

@@ -19,7 +19,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
import conf # noqa: E402 [flake8 lint suppression]
from const import confFileName, logPath # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value, hide_email # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
@@ -80,7 +80,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId = pluginName,
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = notification["GUID"],
watched2 = result,
watched3 = 'null',

View File

@@ -26,7 +26,7 @@ from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value, bytes_to_string, \
sanitize_string, normalize_string # noqa: E402 [flake8 lint suppression]
from database import DB, get_device_stats # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
# Make sure the TIMEZONE for logging is correct
@@ -583,7 +583,7 @@ def publish_notifications(db, mqtt_client):
# Optional: attach meta info
payload["_meta"] = {
"published_at": timeNowDB(),
"published_at": timeNowUTC(),
"source": "NetAlertX",
"notification_GUID": notification["GUID"]
}
@@ -631,7 +631,7 @@ def prepTimeStamp(datetime_str):
except ValueError:
mylog('verbose', [f"[{pluginName}] Timestamp conversion failed of string '{datetime_str}'"])
# Use the current time if the input format is invalid
parsed_datetime = datetime.now(conf.tz)
parsed_datetime = timeNowUTC(as_string=False)
# Convert to the required format with 'T' between date and time and ensure the timezone is included
return parsed_datetime.isoformat() # This will include the timezone offset

View File

@@ -13,7 +13,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
import conf # noqa: E402 [flake8 lint suppression]
from const import confFileName, logPath # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
@@ -63,7 +63,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId = pluginName,
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = notification["GUID"],
watched2 = handleEmpty(response_text),
watched3 = response_status_code,

View File

@@ -15,7 +15,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value, hide_string # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
from database import DB # noqa: E402 [flake8 lint suppression]
@@ -60,7 +60,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId=pluginName,
secondaryId=timeNowDB(),
secondaryId=timeNowUTC(),
watched1=notification["GUID"],
watched2=handleEmpty(response_text),
watched3=response_status_code,

View File

@@ -13,7 +13,7 @@ from const import confFileName, logPath # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value, hide_string # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
from database import DB # noqa: E402 [flake8 lint suppression]
from pytz import timezone # noqa: E402 [flake8 lint suppression]
@@ -61,7 +61,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId = pluginName,
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = notification["GUID"],
watched2 = handleEmpty(response_text),
watched3 = response_status_code,

View File

@@ -11,7 +11,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
import conf # noqa: E402 [flake8 lint suppression]
from const import confFileName, logPath # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
@@ -60,7 +60,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId=pluginName,
secondaryId=timeNowDB(),
secondaryId=timeNowUTC(),
watched1=notification["GUID"],
watched2=result,
watched3='null',

View File

@@ -15,7 +15,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
import conf # noqa: E402 [flake8 lint suppression]
from const import logPath, confFileName # noqa: E402 [flake8 lint suppression]
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value, write_file # noqa: E402 [flake8 lint suppression]
from models.notification_instance import NotificationInstance # noqa: E402 [flake8 lint suppression]
@@ -69,7 +69,7 @@ def main():
# Log result
plugin_objects.add_object(
primaryId = pluginName,
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = notification["GUID"],
watched2 = handleEmpty(response_stdout),
watched3 = handleEmpty(response_stderr),

View File

@@ -4,7 +4,6 @@ import os
import argparse
import sys
import csv
from datetime import datetime
# Register NetAlertX directories
INSTALL_PATH = os.getenv('NETALERTX_APP', '/app')
@@ -13,6 +12,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
from pytz import timezone # noqa: E402 [flake8 lint suppression]
from database import get_temp_db_connection # noqa: E402 [flake8 lint suppression]
@@ -60,7 +60,7 @@ def main():
if overwrite:
filename = 'devices.csv'
else:
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
timestamp = timeNowUTC(as_string=False).strftime('%Y%m%d%H%M%S')
filename = f'devices_{timestamp}.csv'
fullPath = os.path.join(values.location.split('=')[1], filename)

View File

@@ -69,11 +69,9 @@ def cleanup_database(
mylog("verbose", [f"[{pluginName}] Upkeep Database: {dbPath}"])
# Connect to the App database
conn = get_temp_db_connection()
cursor = conn.cursor()
# Reindwex to prevent fails due to corruption
try:
cursor.execute("REINDEX;")
mylog("verbose", [f"[{pluginName}] REINDEX completed"])
@@ -82,25 +80,25 @@ def cleanup_database(
# -----------------------------------------------------
# Cleanup Online History
mylog("verbose", [f"[{pluginName}] Online_History: Delete all but keep latest 150 entries"],)
mylog("verbose", [f"[{pluginName}] Online_History: Delete all but keep latest 150 entries"])
cursor.execute(
"""DELETE from Online_History where "Index" not in (
SELECT "Index" from Online_History
order by Scan_Date desc limit 150)"""
)
mylog("verbose", [f"[{pluginName}] Online_History deleted rows: {cursor.rowcount}"])
# -----------------------------------------------------
# Cleanup Events
mylog("verbose", f"[{pluginName}] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)")
sql = f"""DELETE FROM Events WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')"""
mylog("verbose", [f"[{pluginName}] SQL : {sql}"])
cursor.execute(sql)
# -----------------------------------------------------
# Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry
mylog("verbose", f"[{pluginName}] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)")
mylog("verbose", [f"[{pluginName}] Events deleted rows: {cursor.rowcount}"])
# Build the SQL query to delete entries that exceed the limit per unique "Plugin" column entry
# -----------------------------------------------------
# Plugins_History
mylog("verbose", f"[{pluginName}] Plugins_History: Trim to {str(PLUGINS_KEEP_HIST)} per Plugin")
delete_query = f"""DELETE FROM Plugins_History
WHERE "Index" NOT IN (
SELECT "Index"
@@ -111,17 +109,13 @@ def cleanup_database(
) AS ranked_objects
WHERE row_num <= {str(PLUGINS_KEEP_HIST)}
);"""
cursor.execute(delete_query)
mylog("verbose", [f"[{pluginName}] Plugins_History deleted rows: {cursor.rowcount}"])
# -----------------------------------------------------
# Trim Notifications entries to less than DBCLNP_NOTIFI_HIST setting
# Notifications
histCount = get_setting_value("DBCLNP_NOTIFI_HIST")
mylog("verbose", f"[{pluginName}] Plugins_History: Trim Notifications entries to less than {histCount}")
# Build the SQL query to delete entries
mylog("verbose", f"[{pluginName}] Notifications: Trim to {histCount}")
delete_query = f"""DELETE FROM Notifications
WHERE "Index" NOT IN (
SELECT "Index"
@@ -132,16 +126,13 @@ def cleanup_database(
) AS ranked_objects
WHERE row_num <= {histCount}
);"""
cursor.execute(delete_query)
mylog("verbose", [f"[{pluginName}] Notifications deleted rows: {cursor.rowcount}"])
# -----------------------------------------------------
# Trim Workflow entries to less than WORKFLOWS_AppEvents_hist setting
# AppEvents
histCount = get_setting_value("WORKFLOWS_AppEvents_hist")
mylog("verbose", [f"[{pluginName}] Trim AppEvents to less than {histCount}"])
# Build the SQL query to delete entries
delete_query = f"""DELETE FROM AppEvents
WHERE "Index" NOT IN (
SELECT "Index"
@@ -152,38 +143,40 @@ def cleanup_database(
) AS ranked_objects
WHERE row_num <= {histCount}
);"""
cursor.execute(delete_query)
mylog("verbose", [f"[{pluginName}] AppEvents deleted rows: {cursor.rowcount}"])
conn.commit()
# -----------------------------------------------------
# Cleanup New Devices
if HRS_TO_KEEP_NEWDEV != 0:
mylog("verbose", f"[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)")
mylog("verbose", f"[{pluginName}] Devices: Delete New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours")
query = f"""DELETE FROM Devices WHERE devIsNew = 1 AND devFirstConnection < date('now', '-{str(HRS_TO_KEEP_NEWDEV)} hour')"""
mylog("verbose", [f"[{pluginName}] Query: {query} "])
mylog("verbose", [f"[{pluginName}] Query: {query}"])
cursor.execute(query)
mylog("verbose", [f"[{pluginName}] Devices (new) deleted rows: {cursor.rowcount}"])
# -----------------------------------------------------
# Cleanup Offline Devices
if HRS_TO_KEEP_OFFDEV != 0:
mylog("verbose", f"[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_OFFDEV)} hours (HRS_TO_KEEP_OFFDEV setting)")
mylog("verbose", f"[{pluginName}] Devices: Delete Offline Devices older than {str(HRS_TO_KEEP_OFFDEV)} hours")
query = f"""DELETE FROM Devices WHERE devPresentLastScan = 0 AND devLastConnection < date('now', '-{str(HRS_TO_KEEP_OFFDEV)} hour')"""
mylog("verbose", [f"[{pluginName}] Query: {query} "])
mylog("verbose", [f"[{pluginName}] Query: {query}"])
cursor.execute(query)
mylog("verbose", [f"[{pluginName}] Devices (offline) deleted rows: {cursor.rowcount}"])
# -----------------------------------------------------
# Clear New Flag
if CLEAR_NEW_FLAG != 0:
mylog("verbose", f'[{pluginName}] Devices: Clear "New Device" flag for all devices older than {str(CLEAR_NEW_FLAG)} hours (CLEAR_NEW_FLAG setting)')
mylog("verbose", f'[{pluginName}] Devices: Clear "New Device" flag older than {str(CLEAR_NEW_FLAG)} hours')
query = f"""UPDATE Devices SET devIsNew = 0 WHERE devIsNew = 1 AND date(devFirstConnection, '+{str(CLEAR_NEW_FLAG)} hour') < date('now')"""
# select * from Devices where devIsNew = 1 AND date(devFirstConnection, '+3 hour' ) < date('now')
mylog("verbose", [f"[{pluginName}] Query: {query} "])
mylog("verbose", [f"[{pluginName}] Query: {query}"])
cursor.execute(query)
mylog("verbose", [f"[{pluginName}] Devices updated rows (clear new): {cursor.rowcount}"])
# -----------------------------------------------------
# De-dupe (de-duplicate) from the Plugins_Objects table
# TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :(
# De-dupe Plugins_Objects
mylog("verbose", [f"[{pluginName}] Plugins_Objects: Delete all duplicates"])
cursor.execute(
"""
@@ -197,25 +190,20 @@ def cleanup_database(
)
"""
)
mylog("verbose", [f"[{pluginName}] Plugins_Objects deleted rows: {cursor.rowcount}"])
conn.commit()
# Check WAL file size
# WAL + Vacuum
cursor.execute("PRAGMA wal_checkpoint(TRUNCATE);")
cursor.execute("PRAGMA wal_checkpoint(FULL);")
mylog("verbose", [f"[{pluginName}] WAL checkpoint executed to truncate file."])
# Shrink DB
mylog("verbose", [f"[{pluginName}] Shrink Database"])
cursor.execute("VACUUM;")
# Close the database connection
conn.close()
# ===============================================================================
# BEGIN
# ===============================================================================
if __name__ == "__main__":
main()

View File

@@ -22,7 +22,7 @@ from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB, DATETIME_PATTERN # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC, DATETIME_PATTERN # noqa: E402 [flake8 lint suppression]
# Make sure the TIMEZONE for logging is correct
conf.tz = timezone(get_setting_value("TIMEZONE"))
@@ -151,7 +151,7 @@ def main():
watched1=freebox["name"],
watched2=freebox["operator"],
watched3="Gateway",
watched4=timeNowDB(),
watched4=timeNowUTC(),
extra="",
foreignKey=freebox["mac"],
)

View File

@@ -99,7 +99,7 @@
"description": [
{
"language_code": "en_us",
"string": "Selects the ICMP engine to use. <code>ping</code> checks devices individually and works even when the ARP / neighbor cache is empty, but is slower on larger networks. <code>fping</code> scans IP ranges in parallel and is significantly faster, but relies on the system neighbor cache to resolve IP addresses to MAC addresses. For most networks, <code>fping</code> is recommended. The default command arguments <code>ICMP_ARGS</code> are compatible with both modes."
"string": "Selects the ICMP engine to use. <code>ping</code> checks devices individually, works even with an empty ARP/neighbor cache, but is slower on large networks. <code>fping</code> scans IP ranges in parallel and is much faster, but depends on the system neighbor cache, which can delay MAC resolution. For most networks, <code>fping</code> is recommended, unless precise and timely offline/online detection is needed. Default <code>ICMP_ARGS</code> work with both engines."
}
]
},

View File

@@ -12,7 +12,7 @@ INSTALL_PATH = os.getenv('NETALERTX_APP', '/app')
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger, append_line_to_file # noqa: E402 [flake8 lint suppression]
from helper import check_IP_format, get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
@@ -74,7 +74,7 @@ def main():
mylog('verbose', [f'[{pluginName}] Curl Fallback (new_internet_IP|cmd_output): {new_internet_IP} | {cmd_output}'])
# logging
append_line_to_file(logPath + '/IP_changes.log', '[' + str(timeNowDB()) + ']\t' + new_internet_IP + '\n')
append_line_to_file(logPath + '/IP_changes.log', '[' + str(timeNowUTC()) + ']\t' + new_internet_IP + '\n')
plugin_objects = Plugin_Objects(RESULT_FILE)

View File

@@ -11,7 +11,7 @@ INSTALL_PATH = os.getenv('NETALERTX_APP', '/app')
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
@@ -37,7 +37,7 @@ def main():
speedtest_result = run_speedtest()
plugin_objects.add_object(
primaryId = 'Speedtest',
secondaryId = timeNowDB(),
secondaryId = timeNowUTC(),
watched1 = speedtest_result['download_speed'],
watched2 = speedtest_result['upload_speed'],
watched3 = speedtest_result['full_json'],

View File

@@ -3,7 +3,6 @@
import os
import sys
import subprocess
from datetime import datetime
from pytz import timezone
from functools import reduce
@@ -13,6 +12,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
@@ -95,7 +95,7 @@ def parse_neighbors(raw_neighbors: list[str]):
neighbor = {}
neighbor['ip'] = fields[0]
neighbor['mac'] = fields[2]
neighbor['last_seen'] = datetime.now()
neighbor['last_seen'] = timeNowUTC()
# Unknown data
neighbor['hostname'] = '(unknown)'

View File

@@ -529,7 +529,7 @@
},
{
"column": "Watched_Value2",
"mapped_to_column": "cur_NAME",
"mapped_to_column": "scanName",
"css_classes": "col-sm-2",
"show": true,
"type": "label",

View File

@@ -1516,18 +1516,30 @@
},
{
"function": "devSSID",
"events": [
"add_option"
],
"type": {
"dataType": "string",
"elements": [
{
"elementType": "input",
"elementType": "select",
"elementOptions": [],
"transformers": []
}
]
},
"default_value": "",
"options": [],
"options": [
"{value}"
],
"options_params": [
{
"name": "value",
"type": "sql",
"value": "SELECT DISTINCT '' as id, '❌None' as name UNION SELECT devSSID as id, devSSID as name FROM (SELECT devSSID FROM Devices) AS all_devices ORDER BY id;"
}
],
"localized": [
"name",
"description"
@@ -1590,11 +1602,14 @@
},
{
"function": "devVlan",
"events": [
"add_option"
],
"type": {
"dataType": "string",
"elements": [
{
"elementType": "input",
"elementType": "select",
"elementOptions": [],
"transformers": []
}
@@ -1602,7 +1617,16 @@
},
"maxLength": 50,
"default_value": "",
"options": [],
"options": [
"{value}"
],
"options_params": [
{
"name": "value",
"type": "sql",
"value": "SELECT DISTINCT '' as id, '❌None' as name UNION SELECT devVlan as id, devVlan as name FROM (SELECT devVlan FROM Devices) AS all_devices ORDER BY id;"
}
],
"localized": [
"name",
"description"

View File

@@ -11,7 +11,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger, append_line_to_file # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
@@ -213,7 +213,7 @@ def performNmapScan(deviceIPs, deviceMACs, timeoutSec, args):
elif 'PORT' in line and 'STATE' in line and 'SERVICE' in line:
startCollecting = False # end reached
elif startCollecting and len(line.split()) == 3:
newEntriesTmp.append(nmap_entry(ip, deviceMACs[devIndex], timeNowDB(), line.split()[0], line.split()[1], line.split()[2]))
newEntriesTmp.append(nmap_entry(ip, deviceMACs[devIndex], timeNowUTC(), line.split()[0], line.split()[1], line.split()[2]))
newPortsPerDevice += 1
elif 'Nmap done' in line:
duration = line.split('scanned in ')[1]

View File

@@ -6,7 +6,6 @@ Imports devices from Pi-hole v6 API (Network endpoints) into NetAlertX plugin re
import os
import sys
import datetime
import requests
import json
from requests.packages.urllib3.exceptions import InsecureRequestWarning
@@ -18,6 +17,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
pluginName = 'PIHOLEAPI'
from plugin_helper import Plugin_Objects, is_mac # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
@@ -201,7 +201,7 @@ def gather_device_entries():
"""
entries = []
devices = get_pihole_network_devices()
now_ts = int(datetime.datetime.now().timestamp())
now_ts = int(timeNowUTC(as_string=False).timestamp())
for device in devices:
hwaddr = device.get('hwaddr')

View File

@@ -12,7 +12,7 @@ sys.path.append(f"{INSTALL_PATH}/front/plugins")
sys.path.append(f'{INSTALL_PATH}/server')
from logger import mylog # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from const import default_tz, fullConfPath # noqa: E402 [flake8 lint suppression]
@@ -237,7 +237,7 @@ class Plugin_Object:
self.pluginPref = ""
self.primaryId = primaryId
self.secondaryId = secondaryId
self.created = timeNowDB()
self.created = timeNowUTC()
self.changed = ""
self.watched1 = watched1
self.watched2 = watched2

View File

@@ -1,103 +0,0 @@
<?php
// External files
require '/app/front/php/server/init.php';
$method = $_SERVER['REQUEST_METHOD'];
// ----------------------------------------------
// Method to check authorization
function checkAuthorization($method) {
// Retrieve the authorization header
$headers = apache_request_headers();
$auth_header = $headers['Authorization'] ?? '';
$expected_token = 'Bearer ' . getSettingValue('API_TOKEN');
// Verify the authorization token
if ($auth_header !== $expected_token) {
http_response_code(403);
echo 'Forbidden';
displayInAppNoti("[Plugin: SYNC] Incoming data: Incorrect API Token (".$method.")", "error");
exit;
}
}
// ----------------------------------------------
// Function to return JSON response
function jsonResponse($status, $data = '', $message = '') {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode([
'node_name' => getSettingValue('SYNC_node_name'),
'status' => $status,
'message' => $message,
'data_base64' => $data,
'timestamp' => date('Y-m-d H:i:s')
]);
}
// ----------------------------------------------
// MAIN
// ----------------------------------------------
// requesting data (this is a NODE)
if ($method === 'GET') {
checkAuthorization($method);
$apiRoot = getenv('NETALERTX_API') ?: '/tmp/api';
$file_path = rtrim($apiRoot, '/') . '/table_devices.json';
$data = file_get_contents($file_path);
// Prepare the data to return as a JSON response
$response_data = base64_encode($data);
// Return JSON response
jsonResponse(200, $response_data, 'OK');
displayInAppNoti("[Plugin: SYNC] Data sent", "info");
}
// receiving data (this is a HUB)
else if ($method === 'POST') {
checkAuthorization($method);
// Retrieve and decode the data from the POST request
$data = $_POST['data'] ?? '';
$file_path = $_POST['file_path'] ?? '';
$node_name = $_POST['node_name'] ?? '';
$plugin = $_POST['plugin'] ?? '';
$logRoot = getenv('NETALERTX_PLUGINS_LOG') ?: (rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/') . '/plugins');
$storage_path = rtrim($logRoot, '/');
// // check location
// if (!is_dir($storage_path)) {
// echo "Could not open folder: {$storage_path}";
// write_notification("[Plugin: SYNC] Could not open folder: {$storage_path}", "alert");
// http_response_code(500);
// exit;
// }
// Generate a unique file path to avoid overwriting existing files
$encoded_files = glob("{$storage_path}/last_result.{$plugin}.encoded.{$node_name}.*.log");
$decoded_files = glob("{$storage_path}/last_result.{$plugin}.decoded.{$node_name}.*.log");
$files = array_merge($encoded_files, $decoded_files);
$file_count = count($files) + 1;
$file_path_new = "{$storage_path}/last_result.{$plugin}.encoded.{$node_name}.{$file_count}.log";
// Save the decoded data to the file
file_put_contents($file_path_new, $data);
http_response_code(200);
echo 'Data received and stored successfully';
displayInAppNoti("[Plugin: SYNC] Data received ({$file_path_new})", "info");
} else {
http_response_code(405);
echo 'Method Not Allowed';
displayInAppNoti("[Plugin: SYNC] Method Not Allowed", "error");
}
?>

View File

@@ -16,7 +16,7 @@ from utils.plugin_utils import get_plugins_configs, decode_and_rename_files # n
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from const import logPath # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowDB # noqa: E402 [flake8 lint suppression]
from utils.datetime_utils import timeNowUTC # noqa: E402 [flake8 lint suppression]
from utils.crypto_utils import encrypt_data # noqa: E402 [flake8 lint suppression]
from messaging.in_app import write_notification # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
@@ -147,7 +147,7 @@ def main():
message = f'[{pluginName}] Device data from node "{node_name}" written to {log_file_name}'
mylog('verbose', [message])
if lggr.isAbove('verbose'):
write_notification(message, 'info', timeNowDB())
write_notification(message, 'info', timeNowUTC())
# Process any received data for the Device DB table (ONLY JSON)
# Create the file path
@@ -253,7 +253,7 @@ def main():
message = f'[{pluginName}] Inserted "{len(new_devices)}" new devices'
mylog('verbose', [message])
write_notification(message, 'info', timeNowDB())
write_notification(message, 'info', timeNowUTC())
# Commit and close the connection
conn.commit()
@@ -269,7 +269,6 @@ def main():
# Data retrieval methods
api_endpoints = [
"/sync", # New Python-based endpoint
"/plugins/sync/hub.php" # Legacy PHP endpoint
]
@@ -298,7 +297,7 @@ def send_data(api_token, file_content, encryption_key, file_path, node_name, pre
if response.status_code == 200:
message = f'[{pluginName}] Data for "{file_path}" sent successfully via {final_endpoint}'
mylog('verbose', [message])
write_notification(message, 'info', timeNowDB())
write_notification(message, 'info', timeNowUTC())
return True
except requests.RequestException as e:
@@ -307,7 +306,7 @@ def send_data(api_token, file_content, encryption_key, file_path, node_name, pre
# If all endpoints fail
message = f'[{pluginName}] Failed to send data for "{file_path}" via all endpoints'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowDB())
write_notification(message, 'alert', timeNowUTC())
return False
@@ -331,7 +330,7 @@ def get_data(api_token, node_url):
except json.JSONDecodeError:
message = f'[{pluginName}] Failed to parse JSON from {final_endpoint}'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowDB())
write_notification(message, 'alert', timeNowUTC())
return ""
except requests.RequestException as e:
mylog('verbose', [f'[{pluginName}] Error calling {final_endpoint}: {e}'])
@@ -339,7 +338,7 @@ def get_data(api_token, node_url):
# If all endpoints fail
message = f'[{pluginName}] Failed to get data from "{node_url}" via all endpoints'
mylog('verbose', [message])
write_notification(message, 'alert', timeNowDB())
write_notification(message, 'alert', timeNowUTC())
return ""

View File

@@ -1,6 +1,6 @@
## Overview
A plugin allowing for importing devices from a UniFi controller. The plugin also tries to import the network map.
A plugin allowing for importing devices from a UniFi controller. The plugin also tries to import the network map.
### Usage
@@ -9,19 +9,19 @@ Specify the following settings in the Settings section of NetAlertX:
- `UNFIMP_username` - Username used to log in the UNIFI controller.
- `UNFIMP_password` - Password used to log in the UNIFI controller.
- `UNFIMP_host` - Host URL or IP address where the UNIFI controller is hosted (excluding `http://`)
- `UNFIMP_sites` - Name of the sites (usually 'default', check the URL in your UniFi controller UI if unsure. The site id is in the following part of the URL: `https://192.168.1.1:8443/manage/site/this-is-the-site-id/settings/`).
- `UNFIMP_sites` - Name of the sites (usually 'default', check the URL in your UniFi controller UI if unsure. The site id is in the following part of the URL: `https://192.168.1.1:8443/manage/site/this-is-the-site-id/settings/`).
- `UNFIMP_protocol` - https:// or http://
- `UNFIMP_port` - Usually `8443`, `8843`, or `443`
- `UNFIMP_port` - Usually `8443`, `8843`, or `443` (UPSTREAM BUG: Setting `UNFIMP_version='UDMP-unifiOS'` will force `443` see [#1524](https://github.com/netalertx/NetAlertX/issues/1524) or switch to the `UNIFIAPI` plugin)
- `UNFIMP_version` - see below table for details
#### Config overview
| Controller | `UNFIMP_version` | `UNFIMP_port` |
| ------------------------------------------------------ | ------------------------- | ---------------- |
| Cloud Gateway Ultra / UCK cloudkey V2 plus (v4.0.18) | `UDMP-unifiOS` | `443` |
| Docker hosted | `v5` | `8443` (usually) |
| Controller | `UNFIMP_version` | `UNFIMP_port` |
| ------------------------------------------------------ | ------------------------- | ------------------------------------ |
| Cloud Gateway Ultra / UCK cloudkey V2 plus (v4.0.18) | `UDMP-unifiOS` | `443` (BUG: always forced) |
| Docker hosted | `v5` | `8443` (usually) |
### Notes
- It is recommended to create a read-only user in your UniFi controller
- It is recommended to create a read-only user in your UniFi controller

View File

@@ -10,8 +10,8 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402 [flake8 lint suppression]
from logger import mylog, Logger # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath, applicationPath # noqa: E402 [flake8 lint suppression]
from helper import get_setting_value # noqa: E402 [flake8 lint suppression]
from const import logPath, applicationPath, NULL_EQUIVALENTS_SQL # noqa: E402 [flake8 lint suppression]
from scan.device_handling import query_MAC_vendor # noqa: E402 [flake8 lint suppression]
import conf # noqa: E402 [flake8 lint suppression]
from pytz import timezone # noqa: E402 [flake8 lint suppression]
@@ -83,17 +83,16 @@ def update_vendors(plugin_objects):
mylog('verbose', [' Searching devices vendor'])
# Get devices without a vendor
cursor.execute("""SELECT
devMac,
devLastIP,
devName,
devVendor
FROM Devices
WHERE devVendor = '(unknown)'
OR devVendor = '(Unknown)'
OR devVendor = ''
OR devVendor IS NULL
""")
query = f"""
SELECT
devMac,
devLastIP,
devName,
devVendor
FROM Devices
WHERE devVendor IN ({NULL_EQUIVALENTS_SQL}) OR devVendor IS NULL
"""
cursor.execute(query)
devices = cursor.fetchall()
conn.commit()

View File

@@ -2,7 +2,7 @@
require 'php/templates/header.php';
require 'php/templates/modals.php';
?>
<script>
@@ -14,7 +14,7 @@
<!-- Content header--------------------------------------------------------- -->
<!-- Main content ---------------------------------------------------------- -->
<section class="content tab-content">
<section class="content tab-content">
<div class="box box-gray col-xs-12" >
<div class="box-header">
@@ -45,7 +45,7 @@
<select id="formatSelect" class="pointer">
<option value="HTML">HTML</option>
<option value="JSON">JSON</option>
<option value="Text">Text</option>
<option value="Text">Text</option>
</select>
</div>
@@ -80,7 +80,7 @@
const prevButton = document.getElementById('prevButton');
const nextButton = document.getElementById('nextButton');
const formatSelect = document.getElementById('formatSelect');
let currentIndex = -1; // Current report index
// Function to update the displayed data and timestamp based on the selected format and index
@@ -115,7 +115,7 @@
// console.log(notification)
timestamp.textContent = notification.DateTimeCreated;
timestamp.textContent = localizeTimestamp(notification.DateTimeCreated);
notiGuid.textContent = notification.GUID;
currentIndex = index;
@@ -161,17 +161,17 @@
console.log(index)
if (index == -1) {
showModalOk('WARNING', `${getString("report_guid_missing")} <br/> <br/> <code>${guid}</code>`)
showModalOk('WARNING', `${getString("report_guid_missing")} <br/> <br/> <code>${guid}</code>`)
}
// Load the notification with the specified GUID
updateData(formatSelect.value, index);
})
.catch(error => {
console.error('Error:', error);
});
} else {
} else {
// Initial data load
updateData('HTML', -1); // Default format to HTML and load the latest report