Initial commit on next_release branch

This commit is contained in:
jokob-sk
2025-03-10 07:42:44 +11:00
parent f5713d4178
commit 432a4d9d69
52 changed files with 1508 additions and 218 deletions

21
front/appEvents.php Executable file
View File

@@ -0,0 +1,21 @@
<?php
require 'php/templates/header.php';
require 'php/templates/notification.php';
?>
<!-- ----------------------------------------------------------------------- -->
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
<?php
require 'appEventsCore.php';
?>
</div>
<?php
require 'php/templates/footer.php';
?>

View File

@@ -1,12 +1,12 @@
<section class="content">
<div class="nav-tabs-custom app-event-content" style="margin-bottom: 0px;">
<ul id="tabs-location" class="nav nav-tabs col-sm-2">
<li class="left-nav"><a class="col-sm-12" href="#" id="" data-toggle="tab">Events</a></li>
</ul>
<div id="tabs-content-location" class="tab-content col-sm-10">
<table class="table table-striped" id="appevents-table" data-my-dbtable="AppEvents"></table>
</div>
<div class="nav-tabs-custom app-event-content" style="margin-bottom: 0px;">
<ul id="tabs-location" class="nav nav-tabs col-sm-2 hidden">
<li class="left-nav"><a class="col-sm-12" href="#" id="" data-toggle="tab">Events</a></li>
</ul>
<div id="tabs-content-location" class="tab-content col-sm-12">
<table class="table table-striped" id="appevents-table" data-my-dbtable="AppEvents"></table>
</div>
</div>
</section>
@@ -18,75 +18,110 @@ showSpinner()
$(document).ready(function() {
// Load JSON data from the provided URL
$.getJSON('/php/server/query_json.php?file=table_appevents.json', function(data) {
// Process the JSON data and generate UI dynamically
processData(data)
// Load JSON data from the provided URL
$.getJSON('/php/server/query_json.php?file=table_appevents.json', function(data) {
// Process the JSON data and generate UI dynamically
processData(data)
// hide loading dialog
hideSpinner()
});
// hide loading dialog
hideSpinner()
});
});
function processData(data) {
// Create an object to store unique ObjectType values as app event identifiers
var appEventIdentifiers = {};
// Create an object to store unique ObjectType values as app event identifiers
var appEventIdentifiers = {};
// Array to accumulate data for DataTable
var allData = [];
// Array to accumulate data for DataTable
var allData = [];
// Iterate through the data and generate tabs and content dynamically
$.each(data.data, function(index, item) {
// Accumulate data for DataTable
allData.push(item);
});
// Initialize DataTable for all app events
// Iterate through the data and generate tabs and content dynamically
$.each(data.data, function(index, item) {
$('#appevents-table').DataTable({
data: allData,
paging: true,
lengthChange: true,
lengthMenu: [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
searching: true,
ordering: true,
info: true,
autoWidth: false,
pageLength: 25, // Set the default paging to 25
columns: [
{ data: 'DateTimeCreated', title: getString('AppEvents_DateTimeCreated') },
{ data: 'AppEventType', title: getString('AppEvents_Type') },
{ data: 'ObjectType', title: getString('AppEvents_ObjectType') },
{ data: 'ObjectPrimaryID', title: getString('AppEvents_ObjectPrimaryID') },
{ data: 'ObjectSecondaryID', title: getString('AppEvents_ObjectSecondaryID') },
{ data: 'ObjectStatus', title: getString('AppEvents_ObjectStatus') },
{ data: 'Extra', title: getString('AppEvents_Extra') },
{ data: 'ObjectPlugin', title: getString('AppEvents_Plugin') },
// Add other columns as needed
],
// Add column-specific configurations if needed
columnDefs: [
{ className: 'text-center', targets: [3] },
{ width: '80px', targets: [6] },
// ... Add other columnDefs as needed
// Full MAC
{targets: [3, 4],
'createdCell': function (td, cellData, rowData, row, col) {
if (!emptyArr.includes(cellData)){
$(td).html (createDeviceLink(cellData));
} else {
$(td).html ('');
}
} },
]
});
// Accumulate data for DataTable
allData.push(item);
});
console.log(allData);
// Initialize DataTable for all app events
$('#appevents-table').DataTable({
data: allData,
paging: true,
lengthChange: true,
lengthMenu: [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
searching: true,
ordering: true,
info: true,
autoWidth: false,
pageLength: 25, // Set the default paging to 25
columns: [
{ data: 'DateTimeCreated', title: getString('AppEvents_DateTimeCreated') },
{ data: 'AppEventProcessed', title: getString('AppEvents_AppEventProcessed') },
{ data: 'AppEventType', title: getString('AppEvents_Type') },
{ data: 'ObjectType', title: getString('AppEvents_ObjectType') },
{ data: 'ObjectPrimaryID', title: getString('AppEvents_ObjectPrimaryID') },
{ data: 'ObjectSecondaryID', title: getString('AppEvents_ObjectSecondaryID') },
{ data: 'ObjectStatus', title: getString('AppEvents_ObjectStatus') },
{ data: 'ObjectPlugin', title: getString('AppEvents_Plugin') },
{ data: 'ObjectGUID', title: "GUID" },
// Add other columns as needed
],
// Add column-specific configurations if needed
columnDefs: [
{ className: 'text-center', targets: [4] },
{ width: '80px', targets: [7] },
// ... Add other columnDefs as needed
// Full MAC
{targets: [4, 5],
'createdCell': function (td, cellData, rowData, row, col) {
if (!emptyArr.includes(cellData)){
$(td).html (createDeviceLink(cellData));
} else {
$(td).html ('');
}
} },
// Processed
{targets: [1],
'createdCell': function (td, cellData, rowData, row, col) {
// console.log(cellData);
$(td).html (cellData);
}
},
// Datetime
{targets: [0],
'createdCell': function (td, cellData, rowData, row, col) {
let timezone = $("#NAX_TZ").html(); // e.g., 'Europe/Berlin'
let utcDate = new Date(cellData + ' UTC'); // Adding ' UTC' makes it interpreted as UTC time
// Format the date in the desired timezone
let options = {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // Use 24-hour format
timeZone: timezone // Use the specified timezone
};
let localDate = new Intl.DateTimeFormat('en-GB', options).format(utcDate);
// Update the table cell
$(td).html(localDate);
}
},
]
});
// Activate the first tab
$('#tabs-location li:first-child').addClass('active');
$('#tabs-content-location .tab-pane:first-child').addClass('active');
// Activate the first tab
$('#tabs-location li:first-child').addClass('active');
$('#tabs-content-location .tab-pane:first-child').addClass('active');
}
</script>

View File

@@ -1840,6 +1840,47 @@ input[readonly] {
height:50px;
}
/* -----------------------------------------------------------------------------
Workflows
----------------------------------------------------------------------------- */
#workflowContainerWrap .panel-collapse
{
padding: 5px;
}
.workflows .btn-secondary{
color: #000;
}
.workflows .condition-list button
{
margin: 2px;
}
.workflows button
{
/* width:100%; */
}
#workflowContainerWrap
{
display: contents;
}
.workflow-card, .condition-list, .actions-list
{
display: grid;
padding: 5px;
padding-left: 10px;
}
.condition
{
padding: 5px;
padding-left: 10px;
}
/* -----------------------------------------------------------------------------
Floating edit button
----------------------------------------------------------------------------- */

View File

@@ -123,7 +123,7 @@
<!-- page script ----------------------------------------------------------- -->
<script>
var deviceStatus = 'all';
var tableRows = getCache ("nax_parTableRows") == "" ? 10 : getCache ("nax_parTableRows") ;
var tableRows = getCache ("nax_parTableRows") == "" ? 20 : getCache ("nax_parTableRows") ;
var tableOrder = getCache ("nax_parTableOrder") == "" ? [[3,'desc'], [0,'asc']] : JSON.parse(getCache ("nax_parTableOrder")) ;
var tableColumnHide = [];
@@ -737,7 +737,7 @@ function initializeDatatable (status) {
},
'paging' : true,
'lengthChange' : true,
'lengthMenu' : [[10, 25, 50, 100, 500, 100000], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
'lengthMenu' : [[10, 20, 25, 50, 100, 500, 100000], [10, 20, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
'searching' : true,
'ordering' : true,

View File

@@ -17,7 +17,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Check if file parameter is provided
if ($file) {
// Define the folder where files are located
$filePath = "/app/api/" . basename($file);
if ($file == "workflows.json")
{
$filePath = "/app/config/" . basename($file);
} else
{
$filePath = "/app/api/" . basename($file);
}
// Check if the file exists
if (file_exists($filePath)) {
@@ -34,5 +40,38 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
http_response_code(400);
echo json_encode(["error" => "Missing 'file' parameter"]);
}
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Read the input JSON data
$inputData = file_get_contents("php://input");
$decodedData = json_decode($inputData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode(["error" => "Invalid JSON data"]);
exit;
}
// Check if file parameter is provided and is workflows.json
if (!isset($_GET['file']) || $_GET['file'] !== "workflows.json") {
http_response_code(400);
echo json_encode(["error" => "Invalid or missing file parameter"]);
exit;
}
$file = $_GET['file'];
$filePath = "/app/config/" . basename($file);
// Save new workflows.json (replace existing content)
if (file_put_contents($filePath, json_encode($decodedData, JSON_PRETTY_PRINT))) {
http_response_code(200);
echo json_encode(["success" => "Workflows replaced successfully"]);
} else {
http_response_code(500);
echo json_encode(["error" => "Failed to update workflows.json"]);
}
}
else {
http_response_code(405);
echo json_encode(["error" => "Method Not Allowed"]);
}
?>

View File

@@ -150,7 +150,8 @@
let formattedDateTime = `${day}-${month}-${year} ${hour}:${minute}:${second}`;
if (document.getElementById) {
document.getElementById("PIA_Servertime_place").innerHTML = '(' + formattedDateTime + ')';
document.getElementById("NAX_Servertime_plc").innerHTML = '(' + formattedDateTime + ')';
document.getElementById("NAX_TZ").innerHTML = timeZone;
}
setTimeout(update_servertime, 1000); // Call recursively every second
@@ -234,7 +235,13 @@
<!-- Server Name -->
<li>
<div class="header-server-time small">
<div><?php echo gethostname();?></div> <div><span id="PIA_Servertime_place"></span></div>
<div>
<?php echo gethostname();?>
</div>
<div>
<span id="NAX_Servertime_plc"></span>
<span id="NAX_TZ" class="hidden"></span>
</div>
</div>
</li>
@@ -414,18 +421,22 @@
</li>
<!-- Integrations menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php' ) ) ){ echo 'active menu-open'; } ?>">
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php', 'appEvents.php' ) ) ){ echo 'active menu-open'; } ?>">
<a href="#">
<i class="fa fa-fw fa-plug"></i> <span><?= lang('Navigation_Integrations');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php', 'appEvents.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<div class="info-icon-nav"> </div>
<a href="workflows.php"><?= lang('Navigation_Workflows');?></a>
</li>
<li>
<div class="info-icon-nav"> </div>
<a href="appEvents.php"><?= lang('Navigation_AppEvents');?></a>
</li>
<li>
<a href="plugins.php"><?= lang("Navigation_Plugins");?> </a>
</li>

View File

@@ -8,6 +8,7 @@
"About_Design": "",
"About_Exit": "",
"About_Title": "",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "",
"AppEvents_Extra": "",
"AppEvents_GUID": "",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "",
"NETWORK_DEVICE_TYPES_name": "",
"Navigation_About": "",
"Navigation_AppEvents": "",
"Navigation_Devices": "",
"Navigation_Donations": "",
"Navigation_Events": "",

View File

@@ -8,6 +8,7 @@
"About_Design": "Dissenyat per:",
"About_Exit": "Sortir",
"About_Title": "Escàner de seguretat de xarxa i marc de notificacions",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Logged",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "GUID d'esdeveniments d'Aplicació",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Quins tipus de dispositius es poden utilitzar com a dispositius de xarxa a la vista \"xarxa\". El tipus de dispositiu ha de coincidir exactament amb la configuració <code>Tipus</code> dels detalls de dispositiu. Afegir-ho al dispositiu fent servir el botó <code>+</code>. No elimini els tipus existents, només afegir-ne nous.",
"NETWORK_DEVICE_TYPES_name": "Tipus de dispositiu de xarxa",
"Navigation_About": "Sobre",
"Navigation_AppEvents": "",
"Navigation_Devices": "Dispositius",
"Navigation_Donations": "Donacions",
"Navigation_Events": "Esdeveniments",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Actualitza el valor sota. Sigues curós de seguir el format anterior. <b>No hi ha validació.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Deseu els canvis primer abans de comprovar la configuració."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "",
"About_Exit": "",
"About_Title": "",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "",
"AppEvents_Extra": "",
"AppEvents_GUID": "",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "",
"NETWORK_DEVICE_TYPES_name": "",
"Navigation_About": "",
"Navigation_AppEvents": "",
"Navigation_Devices": "",
"Navigation_Donations": "",
"Navigation_Events": "",

View File

@@ -16,6 +16,7 @@
"About_Design": "Entworfen für:",
"About_Exit": "Abmelden",
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "protokolliert",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "Anwendungsereignis-GUID",
@@ -500,6 +501,7 @@
"NTFY_display_name": "NTFY",
"NTFY_icon": "<i class=\"fa fa-terminal\"></i>",
"Navigation_About": "Über",
"Navigation_AppEvents": "",
"Navigation_Devices": "Geräte",
"Navigation_Donations": "Spenden",
"Navigation_Events": "Ereignisse",
@@ -797,4 +799,4 @@
"settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "Designed for:",
"About_Exit": "Sign out",
"About_Title": "Network security scanner & notification framework",
"AppEvents_AppEventProcessed": "Processed",
"AppEvents_DateTimeCreated": "Logged",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "Application Event GUID",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Which device types are allowed to be used as network devices in the Network view. The device type has to match exactly the <code>Type</code> setting on a specific device in Device details. Add it on the Device via the <code>+</code> button. Do not remove existing types, only add new ones.",
"NETWORK_DEVICE_TYPES_name": "Network device types",
"Navigation_About": "About",
"Navigation_AppEvents": "App Events",
"Navigation_Devices": "Devices",
"Navigation_Donations": "Donations",
"Navigation_Events": "Events",

View File

@@ -16,6 +16,7 @@
"About_Design": "Diseñado para:",
"About_Exit": "Salir",
"About_Title": "Escáner de seguridad de la red y marco de notificaciones",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Registrado",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "GUID del evento de aplicación",
@@ -498,6 +499,7 @@
"NTFY_display_name": "NTFY",
"NTFY_icon": "<i class=\"fa fa-terminal\"></i>",
"Navigation_About": "Acerca de",
"Navigation_AppEvents": "",
"Navigation_Devices": "Dispositivos",
"Navigation_Donations": "Donaciones",
"Navigation_Events": "Eventos",

View File

@@ -8,6 +8,7 @@
"About_Design": "Conçu pour:",
"About_Exit": "Se déconnecter",
"About_Title": "Analyse de la sécurité du réseau et cadre de notification",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Connecté",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "GUID dévénements de l'application",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Les types d'appareils autorisés à être utilisés comme appareils réseau dans la vue Réseau. Le type d'appareils doit être identique au paramètre <code>Type</code> d'un appareil dans le détail des appareils. Ajouter le sur l'appareil grâce au bouton <code>+</code>. Ne pas supprimer de valeurs, seulement en ajouter de nouvelles.",
"NETWORK_DEVICE_TYPES_name": "Type d'appareil réseau",
"Navigation_About": "À propos",
"Navigation_AppEvents": "",
"Navigation_Devices": "Appareils",
"Navigation_Donations": "Dons",
"Navigation_Events": "Évènements",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "Progettato per:",
"About_Exit": "Esci",
"About_Title": "Scanner di sicurezza di rete e framework di notifica",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Loggato",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "GUID evento applicazione",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Quali tipi di dispositivo possono essere utilizzati come dispositivi di rete nella vista Rete. Il tipo di dispositivo deve corrispondere esattamente all'impostazione <code>Tipo</code> su un dispositivo specifico nei Dettagli dispositivo. Aggiungilo sul Dispositivo tramite il pulsante <code>+</code>. Non rimuovere i tipi esistenti, aggiungine solo di nuovi.",
"NETWORK_DEVICE_TYPES_name": "Tipi di dispositivi di rete",
"Navigation_About": "Informazioni su",
"Navigation_AppEvents": "",
"Navigation_Devices": "Dispositivi",
"Navigation_Donations": "Donazioni",
"Navigation_Events": "Eventi",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "Designet for:",
"About_Exit": "Logg ut",
"About_Title": "Nettverkssikkerhetsskanner og varslingsrammeverk",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Logget",
"AppEvents_Extra": "Ekstra",
"AppEvents_GUID": "Applikasjon Hendelse GUID",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Hvilke enhetstyper som tillates å brukes som nettverksenheter i nettverksvisningen. Enhetstypen må samsvare med nøyaktig <code>Type</code> Innstillingen på en bestemt enhet i enhetsdetaljer. Ikke fjern eksisterende typer, legg bare til nye.",
"NETWORK_DEVICE_TYPES_name": "Nettverksenhetstyper",
"Navigation_About": "Om",
"Navigation_AppEvents": "",
"Navigation_Devices": "Enheter",
"Navigation_Donations": "Donasjoner",
"Navigation_Events": "Hendelser",

View File

@@ -8,6 +8,7 @@
"About_Design": "Zaprojektowany dla:",
"About_Exit": "Wyloguj",
"About_Title": "Skaner bezpieczeństwa sieciowego i framwork powiadomień",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Zalogowany",
"AppEvents_Extra": "Ekstra",
"AppEvents_GUID": "Aplikacja GUID wydarzeń",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Które typy urządzeń mają zezwolenie na bycie użytym jako urządzenia sieciowe w Widoku Sieci. Typ urządzenia musi dokładnie odpowiadać ustawieniu <code>Typ</code> na konkretnym urządzeniu w Szczegółach urządzenia. Nie usuwaj istniejących typów, tylko dodawaj nowe.",
"NETWORK_DEVICE_TYPES_name": "Typy urządzeń sieciowych",
"Navigation_About": "Informacje o",
"Navigation_AppEvents": "",
"Navigation_Devices": "Urządzenia",
"Navigation_Donations": "Dotacje",
"Navigation_Events": "Wydarzenia",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Zaktualizuj poniższą wartość. Zachowaj ostrożność i postępuj zgodnie z poprzednim formatem. <b>Walidacja nie jest wykonywana.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Zapisz zmiany zanim będziesz testować swoje ustawienia."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "Desenvolvido por:",
"About_Exit": "Sair",
"About_Title": "Analisador de segurança de rede & framework de notificação",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Registrado em",
"AppEvents_Extra": "Adicional",
"AppEvents_GUID": "Evento de aplicação GUID",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "",
"NETWORK_DEVICE_TYPES_name": "",
"Navigation_About": "",
"Navigation_AppEvents": "",
"Navigation_Devices": "",
"Navigation_Donations": "",
"Navigation_Events": "",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": ""
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "Разработан:",
"About_Exit": "Зарегистрироваться",
"About_Title": "Сетевой сканер и система уведомлений",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Журнал",
"AppEvents_Extra": "Дополнительно",
"AppEvents_GUID": "GUID события приложения",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Какие типы устройств разрешено использовать в качестве сетевых устройств в представлении Сеть. Тип устройства должен точно соответствовать настройке <code>Type</code> для конкретного устройства в сведениях об устройстве. Добавьте его на устройство с помощью кнопки <code>+</code>. Не удаляйте существующие типы, а только добавляйте новые.",
"NETWORK_DEVICE_TYPES_name": "Типы сетевых устройств",
"Navigation_About": "О NetAlertX",
"Navigation_AppEvents": "",
"Navigation_Devices": "Устройства",
"Navigation_Donations": "Пожертвования",
"Navigation_Events": "События",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "",
"About_Exit": "Oturum kapat",
"About_Title": "",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "",
"AppEvents_Extra": "Ekstra",
"AppEvents_GUID": "",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "",
"NETWORK_DEVICE_TYPES_name": "",
"Navigation_About": "Hakkında",
"Navigation_AppEvents": "",
"Navigation_Devices": "Cihazlar",
"Navigation_Donations": "",
"Navigation_Events": "",

View File

@@ -8,6 +8,7 @@
"About_Design": "Призначений для:",
"About_Exit": "Вийти",
"About_Title": "Сканер безпеки мережі та структура сповіщень",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "Зареєстровано",
"AppEvents_Extra": "Екстра",
"AppEvents_GUID": "GUID події програми",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "Які типи пристроїв дозволено використовувати як мережеві пристрої в поданні мережі. Тип пристрою має точно відповідати налаштуванню <code>Тип</code> на певному пристрої в Деталях пристрою. Додайте його на пристрій за допомогою кнопки <code>+</code>. Не видаляйте існуючі типи, лише додайте нові.",
"NETWORK_DEVICE_TYPES_name": "Типи мережевих пристроїв",
"Navigation_About": "про",
"Navigation_AppEvents": "",
"Navigation_Devices": "Пристрої",
"Navigation_Donations": "Пожертви",
"Navigation_Events": "Події",
@@ -716,4 +718,4 @@
"settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>",
"test_event_icon": "fa-vial-circle- check",
"test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни."
}
}

View File

@@ -8,6 +8,7 @@
"About_Design": "设计用于:",
"About_Exit": "登出",
"About_Title": "网络安全扫描器和通知框架",
"AppEvents_AppEventProcessed": "",
"AppEvents_DateTimeCreated": "已记录",
"AppEvents_Extra": "额外的",
"AppEvents_GUID": "应用程序事件 GUID",
@@ -464,6 +465,7 @@
"NETWORK_DEVICE_TYPES_description": "哪些设备类型允许在网络视图中用作网络设备。设备类型必须与设备详细信息中特定设备上的 <code>Type</code> 设置完全匹配。请勿删除现有类型,仅添加新类型。",
"NETWORK_DEVICE_TYPES_name": "网络设备类型",
"Navigation_About": "关于",
"Navigation_AppEvents": "",
"Navigation_Devices": "设备",
"Navigation_Donations": "捐款",
"Navigation_Events": "事件",

View File

@@ -293,9 +293,6 @@ def create_sensor(mqtt_client, deviceId, deviceName, sensorType, sensorName, ico
# check previous configs
sensorConfig = sensor_config(deviceId, deviceName, sensorType, sensorName, icon, mac)
mylog('verbose', [f"[{pluginName}] Publishing sensor number {len(mqtt_sensors)}"])
# send if new
if sensorConfig.isNew:

View File

@@ -18,7 +18,7 @@ from const import pluginsPath, fullDbPath, logPath
from helper import timeNowTZ, get_setting_value
from notification import write_notification
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
from pytz import timezone
@@ -53,8 +53,8 @@ def main():
# Initialize the Plugin obj output file
plugin_objects = Plugin_Objects(RESULT_FILE)
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve devices
unknown_devices = device_handler.getUnknown()

View File

@@ -139,6 +139,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, HRS_TO_KEEP_NEWDEV, HRS_TO_KE
);"""
cursor.execute(delete_query)
conn.commit()
# -----------------------------------------------------

View File

@@ -23,7 +23,7 @@ from logger import mylog, Logger, append_line_to_file
from helper import timeNowTZ, get_setting_value
from const import logPath, applicationPath, fullDbPath
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
from pytz import timezone
@@ -57,8 +57,8 @@ def main():
# Initialize the Plugin obj output file
plugin_objects = Plugin_Objects(RESULT_FILE)
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve devices
all_devices = device_handler.getAll()

View File

@@ -18,7 +18,7 @@ from const import pluginsPath, fullDbPath, logPath
from helper import timeNowTZ, get_setting_value
from notification import write_notification
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
from pytz import timezone
@@ -53,8 +53,8 @@ def main():
# Initialize the Plugin obj output file
plugin_objects = Plugin_Objects(RESULT_FILE)
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve devices
unknown_devices = device_handler.getUnknown()

View File

@@ -24,7 +24,7 @@ from logger import mylog, Logger, append_line_to_file
from helper import timeNowTZ, get_setting_value, extract_between_strings, extract_ip_addresses, extract_mac_addresses
from const import logPath, applicationPath, fullDbPath
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
from pytz import timezone

View File

@@ -23,7 +23,7 @@ from logger import mylog, Logger, append_line_to_file
from helper import timeNowTZ, get_setting_value
from const import logPath, applicationPath, fullDbPath
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
from pytz import timezone
@@ -55,8 +55,8 @@ def main():
# Initialize the Plugin obj output file
plugin_objects = Plugin_Objects(RESULT_FILE)
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve devices
unknown_devices = device_handler.getUnknown()

View File

@@ -251,12 +251,12 @@ def main():
mylog("verbose", [f"[{pluginName}] starting execution"])
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
db = DB() # instance of class DB
db.open()
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve configuration settings
# these should be self-explanatory
omada_sites = []

View File

@@ -19,7 +19,7 @@ from const import pluginsPath, fullDbPath, logPath
from helper import timeNowTZ, get_setting_value
from notification import write_notification
from database import DB
from device import Device_obj
from models.device_instance import DeviceInstance
import conf
# Make sure the TIMEZONE for logging is correct
@@ -54,8 +54,8 @@ def main():
db = DB() # instance of class DB
db.open()
# Create a Device_obj instance
device_handler = Device_obj(db)
# Create a DeviceInstance instance
device_handler = DeviceInstance(db)
# Retrieve devices
if 'offline' in devices_to_wake:

View File

@@ -10,7 +10,7 @@
<div class="content-wrapper">
<?php
require 'appEventsCore.php';
require 'workflowsCore.php';
?>

385
front/workflowsCore.php Executable file
View File

@@ -0,0 +1,385 @@
<?php
//------------------------------------------------------------------------------
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
?>
<section class="content workflows">
<div id="workflowContainerWrap" class="bg-grey-dark color-palette col-sm-12 box-default box-info ">
<div id="workflowContainer"></div>
</div>
<div id="buttons" class="buttons col-sm-12">
<div class="add-workflow col-sm-6">
<button type="button" class="btn btn-primary btn-default pa-btn bg-green" id="save" onclick="addWorkflow()">
<?= lang('Gen_Add');?>
</button>
</div>
<div class="save-workflows col-sm-6">
<button type="button" class="btn btn-primary btn-default pa-btn bg-green" id="save" onclick="saveWorkflows()">
<?= lang('DevDetail_button_Save');?>
</button>
</div>
</div>
</section>
<script>
let workflows = [];
let fieldOptions = [
"devMac", "devName", "devOwner", "devType", "devVendor", "devFavorite",
"devGroup", "devComments", "devFirstConnection", "devLastConnection",
"devLastIP", "devStaticIP", "devScan", "devLogEvents", "devAlertEvents",
"devAlertDown", "devSkipRepeated", "devLastNotification", "devPresentLastScan",
"devIsNew", "devLocation", "devIsArchived", "devParentMAC", "devParentPort",
"devIcon", "devGUID", "devSite", "devSSID", "devSyncHubNode", "devSourcePlugin"
];
let triggerTypes = [
"Devices", "Plugins_Objects"
];
let operatorTypes = [
"equals", "contains" , "regex"
];
let actionTypes = [
"update_field", "run_plugin"
];
// --------------------------------------
// Retrieve and process the data
function getData() {
showSpinner();
getSetting()
$.get('php/server/query_json.php?file=workflows.json', function (res) {
workflows = res;
console.log(workflows);
renderWorkflows();
hideSpinner();
});
}
// --------------------------------------
// Render all workflows
function renderWorkflows() {
let $container = $("#workflowContainer");
$container.empty(); // Clear previous UI
$.each(workflows, function (index, wf) {
let $wfElement = generateWorkflowUI(wf, index);
$container.append($wfElement);
});
}
// --------------------------------------
// Generate UI for a single workflow
function generateWorkflowUI(wf, index) {
let $wfContainer = $("<div>", {
class: "workflow-card box box-solid box-primary panel panel-default",
id: `wf-${index}-container`
});
// Workflow Name
let $wfLinkWrap = $("<div>",
{
class: " ",
id: `wf-${index}-header`
}
)
let $wfHeaderLink = $("<a>",
{
"class": "",
"data-toggle": "collapse",
"data-parent": "#workflowContainer",
"aria-expanded": false,
"href" : `#wf-${index}-collapsible-panel`
}
)
let $wfHeaderHeading = $("<h4>",
{
class: "panel-title"
}
).text(wf.name)
$wfContainer.append($wfHeaderLink.append($wfLinkWrap.append($wfHeaderHeading)));
// Collapsible panel start
let $wfCollapsiblePanel = $("<div>", {
class: "panel-collapse collapse ",
id: `wf-${index}-collapsible-panel`
});
let $wfNameInput = createEditableInput("Workflow name", wf.name, `wf-name-${index}`, "workflow-name-input", function(newValue) {
console.log(`Saved new value: ${newValue}`);
wf.name = newValue; // Update the workflow object with the new name
});
$wfCollapsiblePanel.append($wfNameInput)
// Trigger Section with dropdowns
let $triggerSection = $("<div>",
{
class: "condition-list box box-secondary"
}
).append("<strong>Trigger:</strong> ");
let $triggerTypeDropdown = createEditableDropdown("Trigger Type", triggerTypes, wf.trigger.object_type, `trigger-${index}-type`, function(newValue) {
wf.trigger.object_type = newValue; // Update trigger's object_type
});
let $eventTypeDropdown = createEditableDropdown("Event Type", ["update", "create", "delete"], wf.trigger.event_type, `event-${index}-type`, function(newValue) {
wf.trigger.event_type = newValue; // Update trigger's event_type
});
$triggerSection.append($triggerTypeDropdown);
$triggerSection.append($eventTypeDropdown);
$wfCollapsiblePanel.append($triggerSection);
// Conditions
let $conditionsContainer = $("<div>").append("<strong>Conditions:</strong>");
$conditionsContainer.append(renderConditions(wf.conditions));
$wfCollapsiblePanel.append($conditionsContainer);
// Actions with action.field as dropdown
let $actionsContainer = $("<div>",
{
class: "actions-list box box-secondary"
}
).append("<strong>Actions:</strong>");
$.each(wf.actions, function (_, action) {
let $actionEl = $("<div>");
// Dropdown for action.field
let $fieldDropdown = createEditableDropdown("Field", fieldOptions, action.field, `action-${index}-field`, function(newValue) {
action.field = newValue; // Update action.field when a new value is selected
});
// Dropdown for action.type
let $actionDropdown= createEditableDropdown("Action", actionTypes, action.field, `action-${index}-type`, function(newValue) {
action.field = newValue; // Update action.field when a new value is selected
});
// Action Value Input (Editable)
let $actionValueInput = createEditableInput("Value", action.value, `action-${index}-value`, "action-value-input", function(newValue) {
action.value = newValue; // Update action.value when saved
});
$actionEl.append($actionDropdown);
$actionEl.append($fieldDropdown);
$actionEl.append($actionValueInput);
$actionsContainer.append($actionEl);
});
// add conditions group button
let $actionAddButton = $("<button>", {
class : "btn btn-secondary "
}).text("Add Action")
$actionsContainer.append($actionAddButton)
$wfCollapsiblePanel.append($actionsContainer);
$wfContainer.append($wfCollapsiblePanel)
return $wfContainer;
}
// --------------------------------------
// Render conditions recursively
function renderConditions(conditions) {
let $conditionList = $("<div>", {
class: "condition-list panel "
});
$.each(conditions, function (index, condition) {
if (condition.logic) {
let $nestedCondition = $("<div>",
{
class : "condition box box-secondary"
}
);
let $logicDropdown = createEditableDropdown("Logic Rules", ["AND", "OR"], condition.logic, `logic-${condition.field}`, function(newValue) {
condition.logic = newValue; // Update condition logic when a new value is selected
});
$nestedCondition.append($logicDropdown);
$conditionListNested = renderConditions(condition.conditions)
// add conditions group button
let $conditionAddButton = $("<button>", {
class : "btn btn-secondary "
}).text("Add Condition")
$conditionListNested.append($conditionAddButton);
$nestedCondition.append($conditionListNested); // Recursive call for nested conditions
$conditionList.append($nestedCondition);
} else {
let $conditionItem = $("<div>",
{
class: "panel"
});
// Create dropdown for condition field
let $fieldDropdown = createEditableDropdown("Field", fieldOptions, condition.field, `condition-${index}-field-${condition.field}`, function(newValue) {
condition.field = newValue; // Update condition field when a new value is selected
});
// Create dropdown for operator
let $operatorDropdown = createEditableDropdown("Operator", operatorTypes, condition.operator, `condition-${index}operator-${condition.field}`, function(newValue) {
condition.operator = newValue; // Update operator when a new value is selected
});
// Editable input for condition value
let $editableInput = createEditableInput("Condition Value", condition.value, `condition-${index}-value-${condition.field}`, "condition-value-input", function(newValue) {
condition.value = newValue; // Update condition value when saved
});
$conditionItem.append($fieldDropdown); // Append field dropdown
$conditionItem.append($operatorDropdown); // Append operator dropdown
$conditionItem.append($editableInput); // Append editable input for condition value
$conditionList.append($conditionItem);
}
});
// add conditions group button
let $conditionsGroupAddButton = $("<button>", {
class : "btn btn-secondary"
}).text("Add Condition Group")
$conditionList.append($conditionsGroupAddButton);
return $conditionList;
}
// --------------------------------------
// Render SELECT Dropdown with Predefined Values
function createEditableDropdown(labelText, options, selectedValue, id, onSave) {
let $wrapper = $("<div>", {
class: "form-group col-xs-12"
});
let $label = $("<label>", {
for: id,
class: "col-sm-4 col-xs-12 control-label "
}).text(labelText);
// Create select wrapper
let $selectWrapper = $("<div>", {
class: "col-sm-8 col-xs-12"
});
// Create select element
let $select = $("<select>", {
id: id,
class: "form-control col-sm-8 col-xs-12"
});
// Add options to the select dropdown
$.each(options, function (_, option) {
let $option = $("<option>", { value: option }).text(option);
if (option === selectedValue) {
$option.attr("selected", "selected"); // Set the default selection
}
$select.append($option);
});
// Trigger onSave when the selection changes
$select.on("change", function() {
let newValue = $select.val();
console.log(`Selected new value: ${newValue}`);
if (onSave && typeof onSave === "function") {
onSave(newValue); // Call onSave callback with the new value
}
});
$wrapper.append($label);
$wrapper.append($selectWrapper.append($select));
return $wrapper;
}
// --------------------------------------
// Render INPUT HTML element
function createEditableInput(labelText, value, id, className = "", onSave = null) {
// prepare wrapper
$wrapper = $("<div>", {
class: "form-group col-xs-12"
});
let $label = $("<label>", {
for: id,
class: "col-sm-4 col-xs-12 control-label "
}).text(labelText);
// Create input wrapper
let $inputWrapper = $("<div>", {
class: "col-sm-8 col-xs-12"
});
let $input = $("<input>", {
type: "text",
id: id,
value: value,
class: className + " col-sm-8 col-xs-12 form-control "
});
// Optional: Add a change event listener to update the workflow name
$input.on("change", function () {
let newValue = $input.val();
console.log(`Value changed to: ${newValue}`);
});
// Trigger onSave when the user presses Enter or the input loses focus
$input.on("blur keyup", function (e) {
if (e.type === "blur" || e.key === "Enter") {
if (onSave && typeof onSave === "function") {
onSave($input.val()); // Call the onSave callback with the new value
}
}
});
$wrapper.append($label)
$wrapper.append($inputWrapper.append($input))
return $wrapper;
}
// --------------------------------------
// Initialize
$(document).ready(function () {
getData();
});
</script>