mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-08 11:11:38 -07:00
Compare commits
56 Commits
3473fabdbf
...
v24.9.12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcc43d1f3c | ||
|
|
8f35bf36ff | ||
|
|
1548168eba | ||
|
|
2e35bac6ec | ||
|
|
ba348fc4c2 | ||
|
|
d3337e75a9 | ||
|
|
9e0bc043b0 | ||
|
|
29fdd0b115 | ||
|
|
48e92a186e | ||
|
|
1dcb66e972 | ||
|
|
fa0d6d312d | ||
|
|
a19fe342e7 | ||
|
|
c4fc68cac8 | ||
|
|
3a050c31a7 | ||
|
|
2cd406a390 | ||
|
|
b086417686 | ||
|
|
dbecbfc85f | ||
|
|
3f9e4c4425 | ||
|
|
4fd1869bde | ||
|
|
78025a376c | ||
|
|
615fd08f5b | ||
|
|
4839211fe1 | ||
|
|
19aaa92fa3 | ||
|
|
43aa40efbb | ||
|
|
95f48cb70d | ||
|
|
8c0da1d0df | ||
|
|
b0d07a6adc | ||
|
|
ee23ae19f7 | ||
|
|
0c73e49245 | ||
|
|
899a0c3608 | ||
|
|
d188b640e4 | ||
|
|
a95eb45924 | ||
|
|
f737a71939 | ||
|
|
9df97e0e33 | ||
|
|
4ce7077599 | ||
|
|
605a33330b | ||
|
|
9bd5ff10b4 | ||
|
|
45d3be2439 | ||
|
|
46209e3e47 | ||
|
|
9b9836cae2 | ||
|
|
89be97bfb2 | ||
|
|
3e4f64a7c6 | ||
|
|
50fbd6e616 | ||
|
|
5a96ad2304 | ||
|
|
25667014fc | ||
|
|
955472ef5c | ||
|
|
e32b60cafc | ||
|
|
3033c617fa | ||
|
|
1688836b4f | ||
|
|
f30b6b7fc1 | ||
|
|
0c5c754f38 | ||
|
|
da21ee6477 | ||
|
|
3a268add06 | ||
|
|
03b610a6ec | ||
|
|
38f70fd045 | ||
|
|
ae1673c1c3 |
28
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
28
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -9,20 +9,6 @@ body:
|
||||
options:
|
||||
- label: I have searched the existing open and closed issues
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Am I willing to test this? 🧪
|
||||
description: I rely on the community to test unreleased features. If you are requesting a feature, please be willing to test it within 48h of test request. Otherwise, the feature might be pulled from the code base.
|
||||
options:
|
||||
- label: I will do my best to test this feature on the `netlertx-dev` image when requested within 48h and report bugs to help deliver a great user experience for everyone and not to break existing installations.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Can I help implement this? 👩💻👨💻
|
||||
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs
|
||||
options:
|
||||
- label: "Yes"
|
||||
- label: "No"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe
|
||||
@@ -50,3 +36,17 @@ body:
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Am I willing to test this? 🧪
|
||||
description: I rely on the community to test unreleased features. If you are requesting a feature, please be willing to test it within 48h of test request. Otherwise, the feature might be pulled from the code base.
|
||||
options:
|
||||
- label: I will do my best to test this feature on the `netlertx-dev` image when requested within 48h and report bugs to help deliver a great user experience for everyone and not to break existing installations.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Can I help implement this? 👩💻👨💻
|
||||
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs
|
||||
options:
|
||||
- label: "Yes"
|
||||
- label: "No"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM alpine:3.20 as builder
|
||||
FROM alpine:3.20 AS builder
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache bash python3 python3-dev gcc musl-dev libffi-dev openssl-dev \
|
||||
@@ -21,7 +21,7 @@ RUN pip install netifaces tplink-omada-client pycryptodome requests paho-mqtt sc
|
||||
&& bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"
|
||||
|
||||
# second stage
|
||||
FROM alpine:3.20 as runner
|
||||
FROM alpine:3.20 AS runner
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# default UID and GID
|
||||
ENV USER=pi USER_ID=1000 USER_GID=1000 PORT=20211
|
||||
ENV USER=pi USER_ID=1000 USER_GID=1000 PORT=20211
|
||||
#TZ=Europe/London
|
||||
|
||||
# Todo, figure out why using a workdir instead of full paths don't work
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# 🖧🔍 Network scanner & notification framework
|
||||
|
||||
Get visibility of what's going on on your WIFI/LAN network. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
|
||||
|
||||
[](https://github.com/jokob-sk/NetAlertX)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||
[](https://github.com/jokob-sk/NetAlertX/releases)
|
||||
[](https://discord.gg/UQnnHNYV)
|
||||
|
||||
# 🖧🔍 Network scanner & notification framework
|
||||
|
||||
Get visibility of what's going on on your WIFI/LAN network. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
|
||||
|
||||
|
||||
| 🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/netalertx) | 📑 [Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) |🆕 [Release notes](https://github.com/jokob-sk/NetAlertX/releases) | 📚 [All Docs](https://github.com/jokob-sk/NetAlertX/tree/main/docs) |
|
||||
|----------------------|----------------------| ----------------------| ----------------------|
|
||||
|
||||
@@ -64,7 +64,9 @@ services:
|
||||
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
|
||||
# ---------------------------------------------------------------------------
|
||||
environment:
|
||||
# - APP_CONF_OVERRIDE={"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","UI_dark_mode":"True"}
|
||||
- TZ=${TZ}
|
||||
- PORT=${PORT}
|
||||
- PORT=${PORT}
|
||||
# ❗ DANGER ZONE BELOW - Setting ALWAYS_FRESH_INSTALL=true will delete the content of the /db & /config folders
|
||||
- ALWAYS_FRESH_INSTALL=${ALWAYS_FRESH_INSTALL}
|
||||
|
||||
|
||||
@@ -41,6 +41,16 @@ if [ "$ALWAYS_FRESH_INSTALL" = true ]; then
|
||||
rm -rf "$INSTALL_DIR_OLD/db/"*
|
||||
fi
|
||||
|
||||
# OVERRIDE settings: Handling APP_CONF_OVERRIDE
|
||||
# Check if APP_CONF_OVERRIDE is set
|
||||
if [ -z "$APP_CONF_OVERRIDE" ]; then
|
||||
echo "APP_CONF_OVERRIDE is not set. Skipping config file creation."
|
||||
else
|
||||
# Save the APP_CONF_OVERRIDE env variable as a JSON file
|
||||
echo "$APP_CONF_OVERRIDE" > "${INSTALL_DIR}/config/app_conf_override.json"
|
||||
echo "Config file saved to ${INSTALL_DIR}/config/app_conf_override.json"
|
||||
fi
|
||||
|
||||
# 🔻 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2024
|
||||
|
||||
# Check if pialert.db exists, then create a symbolic link to app.db
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
| Pholus_Scan | Scan results of the Pholus python network penetration script. | ![Screen8][screen8] |
|
||||
| Plugins_Events | For capturing events exposed by a plugin via the `last_result.log` file. If unique then saved into the `Plugins_Objects` table. Entries are deleted once processed and stored in the `Plugins_History` and/or `Plugins_Objects` tables. | ![Screen10][screen10] |
|
||||
| Plugins_History | History of all entries from the `Plugins_Events` table | ![Screen11][screen11] |
|
||||
| Plugins_Language_Strings | Language strings colelcted from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] |
|
||||
| Plugins_Language_Strings | Language strings collected from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] |
|
||||
| Plugins_Objects | Unique objects detected by individual plugins. | ![Screen13][screen13] |
|
||||
| Sessions | Used to display sessions in the charts | ![Screen15][screen15] |
|
||||
| Settings | Database representation of the sum of all settings from `app.conf` and plugins coming from `config.json` files. | ![Screen16][screen16] |
|
||||
|
||||
@@ -15,6 +15,7 @@ You need to specify the network interface and the network mask. You can also con
|
||||
* One subnet: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0']`
|
||||
* Two subnets: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0','192.168.1.0/24 --interface=eth1 -vlan=107']`
|
||||
|
||||
If you get timeout messages, decrease the network mask (e.g.: from a `/16` to `/24`) or increase the `TIMEOUT` setting (e.g.: `ARPSCAN_RUN_TIMEOUT` to `300` (a timeout of 5min)) for the plugin and the interval between scans (e.g.: `ARPSCAN_RUN_SCHD` to `*/10 * * * *` (scans every 10 min)).
|
||||
|
||||
## Explanation
|
||||
|
||||
|
||||
@@ -745,6 +745,18 @@ height: 50px;
|
||||
.infobox_label {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
.deviceSelector
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.deviceSelector input
|
||||
{
|
||||
width: 100% !important;
|
||||
display: inline-grid;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
/* report */
|
||||
/* --------------------------------------------------------- */
|
||||
@@ -1079,6 +1091,27 @@ input[readonly] {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#settingsPage .select2-selection
|
||||
{
|
||||
width: initial;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#settingsPage .select2-selection
|
||||
{
|
||||
background-color: rgb(96, 96, 96);
|
||||
}
|
||||
#settingsPage .select2-container
|
||||
{
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#settingsPage .select2-container .selection
|
||||
{
|
||||
width: 100% !important;
|
||||
display: inline-grid;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* Devices page */
|
||||
/* ----------------------------------------------------------------- */
|
||||
@@ -1110,18 +1143,18 @@ input[readonly] {
|
||||
cursor: -webkit-grab;
|
||||
}
|
||||
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple .select2-selection__choice
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice
|
||||
{
|
||||
background-color:#258744;
|
||||
background-color:#258744 !important;
|
||||
}
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple
|
||||
.select2-container--default .select2-selection--multiple
|
||||
{
|
||||
background-color:#606060;
|
||||
background-color:#606060 !important;
|
||||
}
|
||||
|
||||
.select2-container .select2-dropdown
|
||||
{
|
||||
background-color:#606060;
|
||||
background-color:#606060 !important;
|
||||
}
|
||||
|
||||
.networkPageHelp{
|
||||
|
||||
@@ -693,7 +693,6 @@ if ($ENABLED_DARKMODE === True) {
|
||||
|
||||
var pos = -1;
|
||||
var parPeriod = 'Front_Details_Period';
|
||||
var parTab = 'Front_Details_Tab';
|
||||
var parSessionsRows = 'Front_Details_Sessions_Rows';
|
||||
var parEventsRows = 'Front_Details_Events_Rows';
|
||||
var parEventsHide = 'Front_Details_Events_Hide';
|
||||
@@ -736,7 +735,7 @@ function main () {
|
||||
$('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeTabs();
|
||||
initializeTabsNew();
|
||||
initializeiCheck();
|
||||
initializeCombos();
|
||||
initializeDatatables();
|
||||
@@ -763,17 +762,6 @@ function main () {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function initializeTabs () {
|
||||
// Activate panel
|
||||
$('.nav-tabs a[id='+ tab +']').tab('show');
|
||||
|
||||
// When changed save new current tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
setParameter (parTab, $(e.target).attr('id'));
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function initializeiCheck () {
|
||||
// Blue
|
||||
|
||||
@@ -137,136 +137,70 @@
|
||||
<!-- page script ----------------------------------------------------------- -->
|
||||
<script>
|
||||
var deviceStatus = 'all';
|
||||
var parTableRows = 'Front_Devices_Rows';
|
||||
var parTableOrder = 'Front_Devices_Order';
|
||||
var tableRows = 10;
|
||||
var tableOrder = [[3,'desc'], [0,'asc']];
|
||||
var tableRows = getCookie ("nax_parTableRows") == "" ? 10 : getCookie ("nax_parTableRows") ;
|
||||
var tableOrder = getCookie ("nax_parTableOrder") == "" ? [[3,'desc'], [0,'asc']] : JSON.parse(getCookie ("nax_parTableOrder")) ;
|
||||
|
||||
var tableColumnHide = [];
|
||||
var tableColumnOrder = [];
|
||||
var tableColumnVisible = [];
|
||||
|
||||
|
||||
|
||||
|
||||
// Read parameters & Initialize components
|
||||
callAfterAppInitialized(main)
|
||||
showSpinner();
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function main () {
|
||||
|
||||
//initialize the table headers in the correct order
|
||||
var headersDefaultOrder = [
|
||||
getString('Device_TableHead_Name'),
|
||||
getString('Device_TableHead_Owner'),
|
||||
getString('Device_TableHead_Type'),
|
||||
getString('Device_TableHead_Icon'),
|
||||
getString('Device_TableHead_Favorite'),
|
||||
getString('Device_TableHead_Group'),
|
||||
getString('Device_TableHead_FirstSession'),
|
||||
getString('Device_TableHead_LastSession'),
|
||||
getString('Device_TableHead_LastIP'),
|
||||
getString('Device_TableHead_MAC'),
|
||||
getString('Device_TableHead_Status'),
|
||||
getString('Device_TableHead_MAC_full'),
|
||||
getString('Device_TableHead_LastIPOrder'),
|
||||
getString('Device_TableHead_Rowid'),
|
||||
getString('Device_TableHead_Parent_MAC'),
|
||||
getString('Device_TableHead_Connected_Devices'),
|
||||
getString('Device_TableHead_Location'),
|
||||
getString('Device_TableHead_Vendor'),
|
||||
getString('Device_TableHead_Port'),
|
||||
getString('Device_TableHead_GUID'),
|
||||
getString('Device_TableHead_SyncHubNodeName'),
|
||||
getString('Device_TableHead_NetworkSite'),
|
||||
getString('Device_TableHead_SSID')
|
||||
];
|
||||
//initialize the table headers in the correct order
|
||||
var availableColumns = getSettingOptions("UI_device_columns").split(",");
|
||||
var headersDefaultOrder = availableColumns.map(val => getString(val));
|
||||
var selectedColumns = JSON.parse(getSetting("UI_device_columns").replace(/'/g, '"'));
|
||||
|
||||
// generate default order lists of given length
|
||||
var columnsStr = JSON.stringify(Array.from({ length: headersDefaultOrder.length }, (_, i) => i));
|
||||
tableColumnOrder = Array.from({ length: headersDefaultOrder.length }, (_, i) => i);
|
||||
tableColumnVisible = tableColumnOrder;
|
||||
tableColumnVisible = [];
|
||||
|
||||
handleLoadingDialog()
|
||||
// Initialize tableColumnVisible by including all columns from selectedColumns, preserving their order.
|
||||
tableColumnVisible = selectedColumns.map(column => availableColumns.indexOf(column)).filter(index => index !== -1);
|
||||
|
||||
// Add any columns from availableColumns that are not in selectedColumns to the end.
|
||||
const remainingColumns = availableColumns.map((column, index) => index).filter(index => !tableColumnVisible.includes(index));
|
||||
|
||||
// Combine both arrays.
|
||||
tableColumnOrder = tableColumnVisible.concat(remainingColumns);
|
||||
|
||||
// Generate the full array of numbers from 0 to totalLength - 1 of tableColumnOrder
|
||||
const fullArray = Array.from({ length: tableColumnOrder.length }, (_, i) => i);
|
||||
|
||||
// Filter out the elements already present in inputArray
|
||||
const missingNumbers = fullArray.filter(num => !tableColumnVisible.includes(num));
|
||||
|
||||
// Concatenate the inputArray with the missingNumbers
|
||||
tableColumnOrder = [...tableColumnVisible, ...missingNumbers];
|
||||
|
||||
// render table headers
|
||||
html = '';
|
||||
|
||||
for(index = 0; index < tableColumnOrder.length; index++)
|
||||
{
|
||||
html += '<th>' + headersDefaultOrder[tableColumnOrder[index]] + '</th>';
|
||||
}
|
||||
|
||||
$('#tableDevices tr').html(html);
|
||||
|
||||
// Hide UI elements as per settings
|
||||
// setTimeout(() => {
|
||||
hideUIelements("UI_DEV_SECTIONS")
|
||||
|
||||
// }, 10);
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeDatatable(getUrlAnchor('my_devices'));
|
||||
|
||||
// check if data outdated and show spinner if so
|
||||
handleLoadingDialog()
|
||||
|
||||
|
||||
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
|
||||
cookieColumnsVisibleStr = decodeURI(getCookie("Front_Devices_Columns_Visible")).replaceAll('%2C',',')
|
||||
|
||||
defaultValue = cookieColumnsVisibleStr == "" ? columnsStr : cookieColumnsVisibleStr;
|
||||
|
||||
// get visible columns
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Visible&skipcache', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
// save which columns are in the Devices page visible
|
||||
tableColumnVisible = numberArrayFromString(data);
|
||||
|
||||
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
|
||||
cookieColumnsOrderStr = decodeURI(getCookie("Front_Devices_Columns_Order")).replaceAll('%2C',',')
|
||||
|
||||
defaultValue = cookieColumnsOrderStr == "" ? columnsStr : cookieColumnsOrderStr;
|
||||
|
||||
// get the custom order specified by the user
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Order&skipcache', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
// save the columns order in the Devices page
|
||||
tableColumnOrder = numberArrayFromString(data);
|
||||
|
||||
html = '';
|
||||
|
||||
for(index = 0; index < tableColumnOrder.length; index++)
|
||||
{
|
||||
html += '<th>' + headersDefaultOrder[tableColumnOrder[index]] + '</th>';
|
||||
}
|
||||
|
||||
$('#tableDevices tr').html(html);
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=50¶meter='+ parTableRows, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
|
||||
result = parseInt(result, 10)
|
||||
|
||||
if (Number.isInteger (result) ) {
|
||||
tableRows = result;
|
||||
}
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=[[3,"desc"],[0,"asc"]]¶meter='+ parTableOrder, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
result = JSON.parse(result);
|
||||
|
||||
|
||||
|
||||
if (Array.isArray (result) ) {
|
||||
tableOrder = result;
|
||||
}
|
||||
|
||||
// Initialize components with parameters
|
||||
|
||||
initializeDatatable(getUrlAnchor('my_devices'));
|
||||
|
||||
// check if data outdated and show spinner if so
|
||||
handleLoadingDialog()
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -467,6 +401,11 @@ function initializeDatatable (status) {
|
||||
}
|
||||
|
||||
$.get('api/table_devices.json?nocache=' + Date.now(), function(result) {
|
||||
|
||||
// refresh devices cache
|
||||
devicesListAll_JSON = result["data"]
|
||||
devicesListAll_JSON_str = JSON.stringify(devicesListAll_JSON)
|
||||
setCache('devicesListAll_JSON', devicesListAll_JSON_str)
|
||||
|
||||
// query data
|
||||
getDevicesTotals(result.data);
|
||||
@@ -515,10 +454,6 @@ function initializeDatatable (status) {
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// TODO displayed columns
|
||||
|
||||
|
||||
// Check if the DataTable already exists
|
||||
if ($.fn.dataTable.isDataTable('#tableDevices')) {
|
||||
// The DataTable exists, so destroy it
|
||||
@@ -526,12 +461,12 @@ function initializeDatatable (status) {
|
||||
table.clear().destroy();
|
||||
}
|
||||
|
||||
var table=
|
||||
var table =
|
||||
$('#tableDevices').DataTable({
|
||||
'data' : dataArray["data"],
|
||||
'paging' : true,
|
||||
'lengthChange' : true,
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, 100000], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
|
||||
'searching' : true,
|
||||
|
||||
'ordering' : true,
|
||||
@@ -679,11 +614,11 @@ function initializeDatatable (status) {
|
||||
|
||||
// Save cookie Rows displayed, and Parameters rows & order
|
||||
$('#tableDevices').on( 'length.dt', function ( e, settings, len ) {
|
||||
setParameter (parTableRows, len);
|
||||
setCookie ("nax_parTableRows", len);
|
||||
} );
|
||||
|
||||
$('#tableDevices').on( 'order.dt', function () {
|
||||
setParameter (parTableOrder, JSON.stringify (table.order()) );
|
||||
setCookie ("nax_parTableOrder", JSON.stringify (table.order()) );
|
||||
setCache ('devicesList', getDevicesFromTable(table) );
|
||||
} );
|
||||
|
||||
@@ -703,8 +638,6 @@ function initializeDatatable (status) {
|
||||
// Check if any row is selected
|
||||
var anyRowSelected = $('#tableDevices tr.selected').length > 0;
|
||||
|
||||
console.log(anyRowSelected);
|
||||
|
||||
// Toggle visibility of element with ID 'multiEdit'
|
||||
$('#multiEdit').toggle(anyRowSelected);
|
||||
}, 200);
|
||||
|
||||
@@ -12,7 +12,7 @@ var timerRefreshData = ''
|
||||
|
||||
var emptyArr = ['undefined', "", undefined, null, 'null'];
|
||||
var UI_LANG = "English";
|
||||
const allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "zh_cn", "cs_cz"]; // needs to be same as in lang.php
|
||||
const allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "pt_br", "tr_tr", "zh_cn", "cs_cz"]; // needs to be same as in lang.php
|
||||
var settingsJSON = {}
|
||||
|
||||
|
||||
@@ -212,7 +212,8 @@ function cacheStrings() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// Create a promise for each language
|
||||
const languagePromises = allLanguages.map((language_code) => {
|
||||
languagesToLoad = ['en_us', getLangCode()]
|
||||
const languagePromises = languagesToLoad.map((language_code) => {
|
||||
return new Promise((resolveLang, rejectLang) => {
|
||||
// Fetch core strings and translations
|
||||
|
||||
@@ -267,6 +268,29 @@ function cacheStrings() {
|
||||
function getString(key) {
|
||||
|
||||
function fetchString(key) {
|
||||
|
||||
lang_code = getLangCode();
|
||||
|
||||
let result = getCache(`pia_lang_${key}_${lang_code}`, true);
|
||||
|
||||
if (isEmpty(result)) {
|
||||
result = getCache(`pia_lang_${key}_en_us`, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isAppInitialized()) {
|
||||
return fetchString(key);
|
||||
} else {
|
||||
callAfterAppInitialized(() => fetchString(key));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Get current language ISO code
|
||||
function getLangCode() {
|
||||
|
||||
UI_LANG = getSetting("UI_LANG");
|
||||
|
||||
let lang_code = 'en_us';
|
||||
@@ -310,20 +334,7 @@ function getString(key) {
|
||||
break;
|
||||
}
|
||||
|
||||
let result = getCache(`pia_lang_${key}_${lang_code}`, true);
|
||||
|
||||
if (isEmpty(result)) {
|
||||
result = getCache(`pia_lang_${key}_en_us`, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isAppInitialized()) {
|
||||
return fetchString(key);
|
||||
} else {
|
||||
callAfterAppInitialized(() => fetchString(key));
|
||||
}
|
||||
return lang_code;
|
||||
}
|
||||
|
||||
|
||||
@@ -1135,6 +1146,54 @@ function arraysContainSameValues(arr1, arr2) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Hide elements on the page based on the supplied setting
|
||||
function hideUIelements(settingKey) {
|
||||
|
||||
hiddenSectionsSetting = getSetting(settingKey)
|
||||
|
||||
if(hiddenSectionsSetting != "") // handle if settings not yet initialized
|
||||
{
|
||||
|
||||
sectionsArray = createArray(hiddenSectionsSetting)
|
||||
|
||||
// remove spaces to get IDs
|
||||
var newArray = $.map(sectionsArray, function(value) {
|
||||
return value.replace(/\s/g, '');
|
||||
});
|
||||
|
||||
$.each(newArray, function(index, hiddenSection) {
|
||||
|
||||
if($('#' + hiddenSection))
|
||||
{
|
||||
$('#' + hiddenSection).hide()
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// apply dark mode
|
||||
|
||||
$(document).ready(function() {
|
||||
// Assume getSetting is a function that returns true or false for dark mode
|
||||
if (getSetting("UI_dark_mode") === "True") {
|
||||
// Add the dark mode stylesheet
|
||||
setCookie("UI_dark_mode", "True")
|
||||
$('head').append('<link rel="stylesheet" href="css/dark-patch.css">');
|
||||
// Set the background image for dark mode
|
||||
$('body').attr('style', 'background-image: url(\'img/boxed-bg-dark.png\');');
|
||||
} else {
|
||||
setCookie("UI_dark_mode", "False")
|
||||
// Set the background image for light mode
|
||||
$('body').attr('style', 'background-image: url(\'img/background.png\');');
|
||||
}
|
||||
});
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// initialize
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -1145,7 +1204,7 @@ const sessionStorageKey = "myScriptExecuted_common_js";
|
||||
var completedCalls = []
|
||||
var completedCalls_final = ['cacheSettings', 'cacheStrings', 'cacheDevices'];
|
||||
var completedCallsCount = 0;
|
||||
var completedCallsCount_final = allLanguages.length + 2; // number of language files + cacheDevices + cacheSettings
|
||||
var completedCallsCount_final;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Clearing all the caches
|
||||
@@ -1201,7 +1260,11 @@ function callAfterAppInitialized(callback) {
|
||||
// Check if the code has been executed before by checking sessionStorage
|
||||
function isAppInitialized() {
|
||||
// return arraysContainSameValues(getCache("completedCalls").split(',').filter(Boolean), completedCalls_final);
|
||||
return (parseInt(getCache("completedCallsCount")) == completedCallsCount_final);
|
||||
|
||||
// loading settings + 1 (or 2 language files if not english) + device cache.
|
||||
completedCallsCount_final = getLangCode() == 'en_us' ? 3 : 4 ;
|
||||
|
||||
return (parseInt(getCache("completedCallsCount")) >= completedCallsCount_final);
|
||||
}
|
||||
|
||||
// Define a function that will execute the code only once
|
||||
|
||||
@@ -304,6 +304,54 @@ function removeAllOptions(element) {
|
||||
$(`#${$(element).attr("my-input-to")}`).empty();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Add all options
|
||||
function selectAll(element) {
|
||||
settingsChanged();
|
||||
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
// Iterate over each option within the select element
|
||||
selectElement.find('option').each(function() {
|
||||
// Mark each option as selected
|
||||
$(this).prop('selected', true);
|
||||
});
|
||||
|
||||
// Trigger the 'change' event to notify Bootstrap Select of the changes
|
||||
selectElement.trigger('change');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// UN-Select All
|
||||
function unselectAll(element) {
|
||||
settingsChanged();
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
// Iterate over each option within the select element
|
||||
selectElement.find('option').each(function() {
|
||||
// Unselect each option
|
||||
$(this).prop('selected', false);
|
||||
});
|
||||
|
||||
// Trigger the 'change' event to notify Bootstrap Select of the changes
|
||||
selectElement.trigger('change');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Trigger change to open up the dropdown filed
|
||||
function selectChange(element) {
|
||||
settingsChanged();
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
selectElement.parent().find("input").focus().click();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Function to initialize remove functionality on select options
|
||||
|
||||
@@ -437,8 +485,6 @@ function filterRows(inputText) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
// Event listener for input change
|
||||
$("#settingsSearch").on("input", function () {
|
||||
@@ -568,6 +614,10 @@ function applyTransformers(val, transformers) {
|
||||
val = btoa(val);
|
||||
}
|
||||
break;
|
||||
case "getString":
|
||||
// no change
|
||||
val = val;
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown transformer: ${transformer}`);
|
||||
}
|
||||
@@ -590,6 +640,10 @@ function reverseTransformers(val, transformers) {
|
||||
val = atob(val);
|
||||
}
|
||||
break;
|
||||
case "getString":
|
||||
// retrieve string
|
||||
val = getString(val);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown transformer: ${transformer}`);
|
||||
}
|
||||
@@ -703,8 +757,9 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
|
||||
resultArray = []
|
||||
selectedArray = []
|
||||
cssClass = ""
|
||||
|
||||
|
||||
// determine if options or values are used in teh listing
|
||||
// determine if options or values are used in the listing
|
||||
if (valuesArray.length > 0 && options.length > 0){
|
||||
|
||||
// multiselect list -> options only + selected the ones in valuesArray
|
||||
@@ -722,21 +777,31 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
|
||||
resultArray = options;
|
||||
}
|
||||
|
||||
|
||||
// Create a map to track the index of each item in valuesArray
|
||||
const orderMap = new Map(valuesArray.map((item, index) => [item, index]));
|
||||
|
||||
// Sort resultArray based on the order in valuesArray
|
||||
resultArray.sort((a, b) => {
|
||||
const indexA = orderMap.has(a.id) ? orderMap.get(a.id) : valuesArray.length;
|
||||
const indexB = orderMap.has(b.id) ? orderMap.get(b.id) : valuesArray.length;
|
||||
return indexA - indexB;
|
||||
});
|
||||
|
||||
resultArray.forEach(function(item) {
|
||||
let labelName = item.name;
|
||||
|
||||
labelName = item.name
|
||||
|
||||
if(labelName != '❌None')
|
||||
{
|
||||
labelName = reverseTransformers(labelName, transformers)
|
||||
if (labelName !== '❌None') {
|
||||
labelName = reverseTransformers(labelName, transformers);
|
||||
}
|
||||
|
||||
// needs to happen always if options ued as source
|
||||
let selected = options.length != 0 && valuesArray.includes(item.id) ? 'selected' : '';
|
||||
// Always include selected if options are used as a source
|
||||
let selected = options.length !== 0 && valuesArray.includes(item.id) ? 'selected' : '';
|
||||
|
||||
optionsHtml += `<option class="${cssClass}" value="${item.id}" ${selected}>${labelName}</option>`;
|
||||
});
|
||||
|
||||
|
||||
// Place the resulting HTML into the specified placeholder div
|
||||
$("#" + placeholder).replaceWith(optionsHtml);
|
||||
}
|
||||
|
||||
@@ -68,38 +68,6 @@ function initDeviceSelectors(devicesListAll_JSON) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Hide elements on the page based on the supplied setting
|
||||
function hideUIelements(settingKey) {
|
||||
|
||||
hiddenSectionsSetting = getSetting(settingKey)
|
||||
|
||||
if(hiddenSectionsSetting != "") // handle if settings not yet initialized
|
||||
{
|
||||
|
||||
sectionsArray = createArray(hiddenSectionsSetting)
|
||||
|
||||
// remove spaces to get IDs
|
||||
var newArray = $.map(sectionsArray, function(value) {
|
||||
return value.replace(/\s/g, '');
|
||||
});
|
||||
|
||||
$.each(newArray, function(index, hiddenSection) {
|
||||
|
||||
if($('#' + hiddenSection))
|
||||
{
|
||||
$('#' + hiddenSection).hide()
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Updates the icon preview
|
||||
function updateIconPreview (inputId) {
|
||||
@@ -249,6 +217,7 @@ function initSelect2() {
|
||||
|
||||
// --------------------------------------------------------
|
||||
//Initialize Select2 Elements and make them sortable
|
||||
|
||||
$(function () {
|
||||
// Iterate over each Select2 dropdown
|
||||
$('.select2').each(function() {
|
||||
@@ -283,10 +252,15 @@ function initSelect2() {
|
||||
}
|
||||
}
|
||||
|
||||
// try to initialize select2
|
||||
setTimeout(() => {
|
||||
initSelect2()
|
||||
}, 500);
|
||||
// init select2 after dom laoded
|
||||
window.addEventListener("load", function() {
|
||||
// try to initialize select2
|
||||
setTimeout(() => {
|
||||
initSelect2()
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
console.log("init ui_components.js")
|
||||
@@ -11,25 +11,7 @@
|
||||
# cvc90 2023 https://github.com/cvc90 GNU GPLv3 #
|
||||
#---------------------------------------------------------------------------------#
|
||||
|
||||
// Skin selector config ----------------------------------------------------
|
||||
//
|
||||
// For security reasons, new language files must be entered into this array.
|
||||
// The files in the language directory are compared with this array and only
|
||||
// then accepted.
|
||||
//
|
||||
$pia_installed_skins = array('skin-black-light',
|
||||
'skin-black',
|
||||
'skin-blue-light',
|
||||
'skin-blue',
|
||||
'skin-green-light',
|
||||
'skin-green',
|
||||
'skin-purple-light',
|
||||
'skin-purple',
|
||||
'skin-red-light',
|
||||
'skin-red',
|
||||
'skin-yellow-light',
|
||||
'skin-yellow');
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
?>
|
||||
@@ -38,7 +20,7 @@ $pia_installed_skins = array('skin-black-light',
|
||||
require 'php/templates/header.php';
|
||||
?>
|
||||
<!-- Page ------------------------------------------------------------------ -->
|
||||
<div class="content-wrapper">
|
||||
<div class="content-wrapper" id="maintenancePage">
|
||||
|
||||
<!-- Content header--------------------------------------------------------- -->
|
||||
<section class="content-header">
|
||||
@@ -91,34 +73,6 @@ if (count($latestfiles) > 0)
|
||||
$latestbackup_date = date ("Y-m-d H:i:s", filemtime($latestbackup));
|
||||
}
|
||||
|
||||
|
||||
// Skin selector -----------------------------------------------------------------
|
||||
|
||||
if (isset($_POST['submit']) && submit && isset($_POST['skinselector_set'])) {
|
||||
$pia_skin_set_dir = '../db/';
|
||||
$pia_skin_selector = htmlspecialchars($_POST['skinselector']);
|
||||
if (in_array($pia_skin_selector, $pia_installed_skins)) {
|
||||
foreach ($pia_installed_skins as $file) {
|
||||
unlink ($pia_skin_set_dir.'/setting_'.$file);
|
||||
}
|
||||
foreach ($pia_installed_skins as $file) {
|
||||
if (file_exists($pia_skin_set_dir.'/setting_'.$file)) {
|
||||
$pia_skin_error = True;
|
||||
break;
|
||||
} else {
|
||||
$pia_skin_error = False;
|
||||
}
|
||||
}
|
||||
if ($pia_skin_error == False) {
|
||||
$testskin = fopen($pia_skin_set_dir.'setting_'.$pia_skin_selector, 'w');
|
||||
$pia_skin_test = '';
|
||||
echo("<meta http-equiv='refresh' content='1'>");
|
||||
} else {
|
||||
$pia_skin_test = '';
|
||||
echo("<meta http-equiv='refresh' content='1'>");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Table sizes -----------------------------------------------------------------
|
||||
|
||||
$tableSizesHTML = "";
|
||||
@@ -215,13 +169,7 @@ $db->close();
|
||||
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active">
|
||||
<a id="tab_Settings_id" href="#tab_Settings" data-toggle="tab">
|
||||
<i class="fa fa-cogs"></i>
|
||||
<?= lang('Maintenance_Tools_Tab_UISettings');?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<li class="active">
|
||||
<a id="tab_DBTools_id" href="#tab_DBTools" data-toggle="tab">
|
||||
<i class="fa fa-toolbox"></i>
|
||||
<?= lang('Maintenance_Tools_Tab_Tools');?>
|
||||
@@ -247,84 +195,7 @@ $db->close();
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tab_Settings">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" style="text-align: center;">
|
||||
<form method="post" action="maintenance.php">
|
||||
<div style="display: inline-block; text-align: center;">
|
||||
<select name="skinselector" class="form-control bg-green" style="width:160px; margin-bottom:5px;">
|
||||
<option value=""><?= lang('Maintenance_themeselector_empty');?></option>
|
||||
<option value="skin-black-light">black light</option>
|
||||
<option value="skin-black">black</option>
|
||||
<option value="skin-blue-light">blue light</option>
|
||||
<option value="skin-blue">blue</option>
|
||||
<option value="skin-green-light">green light</option>
|
||||
<option value="skin-green">green</option>
|
||||
<option value="skin-purple-light">purple light</option>
|
||||
<option value="skin-purple">purple</option>
|
||||
<option value="skin-red-light">red light</option>
|
||||
<option value="skin-red">red</option>
|
||||
<option value="skin-yellow-light">yellow light</option>
|
||||
<option value="skin-yellow">yellow</option>
|
||||
</select></div>
|
||||
<div style="display: block;"><input type="submit" name="skinselector_set" value="<?= lang('Maintenance_themeselector_apply');?>" class="btn bg-green" style="width:160px;">
|
||||
<?php // echo $pia_skin_test; ?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="db_info_table_cell" style="padding: 10px; height:40px; text-align:left; vertical-align: middle;">
|
||||
<?= lang('Maintenance_themeselector_text'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a">
|
||||
<button type="button" class="btn bg-green dbtools-button" id="btnToggleDarkmode" onclick="askToggleDarkmode()"><?= lang('Maintenance_Tool_darkmode');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_darkmode_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a">
|
||||
<div class="form-group" >
|
||||
<div class="input-group" >
|
||||
<select id="columnsSelect" class="form-control select2 select2-hidden-accessible" multiple="" style="width: 100%;" tabindex="-1" aria-hidden="true">
|
||||
<option value="0"><?= lang('Device_TableHead_Name');?></option>
|
||||
<option value="1"><?= lang('Device_TableHead_Owner');?></option>
|
||||
<option value="2"><?= lang('Device_TableHead_Type');?></option>
|
||||
<option value="3"><?= lang('Device_TableHead_Icon');?></option>
|
||||
<option value="4"><?= lang('Device_TableHead_Favorite');?></option>
|
||||
<option value="5"><?= lang('Device_TableHead_Group');?></option>
|
||||
<option value="6"><?= lang('Device_TableHead_FirstSession');?></option>
|
||||
<option value="7"><?= lang('Device_TableHead_LastSession');?></option>
|
||||
<option value="8"><?= lang('Device_TableHead_LastIP');?></option>
|
||||
<option value="9"><?= lang('Device_TableHead_MAC');?></option>
|
||||
<option value="10"><?= lang('Device_TableHead_Status');?></option>
|
||||
<option value="11"><?= lang('Device_TableHead_MAC_full');?></option>
|
||||
<option value="12"><?= lang('Device_TableHead_LastIPOrder');?></option>
|
||||
<option value="13"><?= lang('Device_TableHead_Rowid');?></option>
|
||||
<option value="14"><?= lang('Device_TableHead_Parent_MAC');?></option>
|
||||
<option value="15"><?= lang('Device_TableHead_Connected_Devices');?></option>
|
||||
<option value="16"><?= lang('Device_TableHead_Location');?></option>
|
||||
<option value="17"><?= lang('Device_TableHead_Vendor');?></option>
|
||||
<option value="18"><?= lang('Device_TableHead_Port');?></option>
|
||||
<option value="19"><?= lang('Device_TableHead_GUID');?></option>
|
||||
<option value="20"><?= lang('Device_TableHead_SyncHubNodeName');?></option>
|
||||
<option value="21"><?= lang('Device_TableHead_NetworkSite');?></option>
|
||||
<option value="22"><?= lang('Device_TableHead_SSID');?></option>
|
||||
</select>
|
||||
<span class="input-group-addon"><i title="<?= lang('Gen_Save');?>" class="fa fa-save pointer" onclick="saveSelectedColumns();"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_displayed_columns_text');?></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="tab_DBTools">
|
||||
<div class="tab-pane active" id="tab_DBTools">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
@@ -483,7 +354,7 @@ $db->close();
|
||||
<script>
|
||||
|
||||
var emptyArr = ['undefined', "", undefined, null];
|
||||
var selectedTab = 'tab_Settings_id';
|
||||
var selectedTab = 'tab_DBTools_id';
|
||||
|
||||
initializeTabs();
|
||||
|
||||
@@ -709,42 +580,6 @@ function ImportPastedCSV()
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Switch Darkmode
|
||||
function askToggleDarkmode() {
|
||||
// Ask
|
||||
showModalWarning('<?= lang('Maintenance_Tool_darkmode_noti');?>', '<?= lang('Maintenance_Tool_darkmode_noti_text');?>',
|
||||
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Switch');?>', 'ToggleDarkmode');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
function ToggleDarkmode()
|
||||
{
|
||||
// get parameter Front_Dark_Mode_Enabled value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=false&expireMinutes=525600¶meter=Front_Dark_Mode_Enabled', function(data) {
|
||||
var result = JSON.parse(data);
|
||||
if (result) {
|
||||
darkModeEnabled = result == 'true';
|
||||
|
||||
// invert value
|
||||
darkModeEnabled = !darkModeEnabled;
|
||||
|
||||
// save inverted value
|
||||
$.get('php/server/parameters.php?action=set¶meter=Front_Dark_Mode_Enabled&expireMinutes=525600&value='+ darkModeEnabled,
|
||||
function(data) {
|
||||
if (data != "OK") {
|
||||
showMessage (data);
|
||||
setTimeout(function (){location.reload()}, 1000);
|
||||
|
||||
} else {
|
||||
showMessage (data);
|
||||
};
|
||||
} );
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// Clean log file
|
||||
@@ -797,122 +632,56 @@ function scrollDown() {
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Manage displayed columns
|
||||
// --------------------------------------------------------
|
||||
colDefaultOrder = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17'];
|
||||
colDefaultOrderTxt = '[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]';
|
||||
|
||||
|
||||
function saveSelectedColumns () {
|
||||
$.get('php/server/parameters.php?action=set&expireMinutes=525600&value=['+ $('#columnsSelect').val().toString() +']¶meter=Front_Devices_Columns_Visible', function(data) {
|
||||
// save full order of all columns to simplify mapping later on
|
||||
|
||||
colDisplayed = $('#columnsSelect').val();
|
||||
|
||||
colNewOrder = colDisplayed;
|
||||
|
||||
// append the remaining columns in the previous order
|
||||
for(i = 0; i < colDefaultOrder.length; i++)
|
||||
{
|
||||
if(!colDisplayed.includes(colDefaultOrder[i]))
|
||||
{
|
||||
colNewOrder.push(colDefaultOrder[i])
|
||||
}
|
||||
}
|
||||
|
||||
// save the setting in the DB
|
||||
$.get('php/server/parameters.php?action=set&expireMinutes=525600&value=['+ colNewOrder.toString() +']¶meter=Front_Devices_Columns_Order', function(data) {
|
||||
|
||||
showMessage(data);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
function initializeSelectedColumns () {
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+colDefaultOrderTxt+'¶meter=Front_Devices_Columns_Visible', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
tableColumnShow = numberArrayFromString(data);
|
||||
|
||||
for(i=0; i < tableColumnShow.length; i++)
|
||||
{
|
||||
// create the option and append to Select2
|
||||
var option = new Option($('#columnsSelect option[value='+tableColumnShow[i]+']').html(), tableColumnShow[i] , true, true);
|
||||
|
||||
$("#columnsSelect").append(option).trigger('change');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// General initialization
|
||||
// --------------------------------------------------------
|
||||
function initializeTabs () {
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
key = "activeMaintenanceTab"
|
||||
function initializeTabs() {
|
||||
setTimeout(() => {
|
||||
const key = "activeMaintenanceTab";
|
||||
|
||||
// default selection
|
||||
selectedTab = "tab_Settings"
|
||||
let selectedTab = "tab_DBTools_id";
|
||||
|
||||
// the #target from the url
|
||||
target = window.location.hash.substr(1)
|
||||
// the #target from the URL
|
||||
let target = window.location.hash.substr(1);
|
||||
|
||||
|
||||
console.log(selectedTab);
|
||||
|
||||
// get only the part between #...?
|
||||
if(target.includes('?'))
|
||||
{
|
||||
target = target.split('?')[0]
|
||||
if (target.includes('?')) {
|
||||
target = target.split('?')[0];
|
||||
}
|
||||
|
||||
console.log(target);
|
||||
|
||||
// update cookie if target specified
|
||||
if(target != "")
|
||||
{
|
||||
|
||||
if (!selectedTab.endsWith("_id")) {
|
||||
selectedTab = target + "_id";
|
||||
}
|
||||
|
||||
setCache(key, selectedTab) // _id is added so it doesn't conflict with AdminLTE tab behavior
|
||||
if (target) {
|
||||
selectedTab = target.endsWith("_id") ? target : `${target}_id`;
|
||||
setCache(key, selectedTab); // _id is added so it doesn't conflict with AdminLTE tab behavior
|
||||
}
|
||||
|
||||
// get the tab id from the cookie (already overriden by the target)
|
||||
if(!emptyArr.includes(getCache(key)))
|
||||
{
|
||||
selectedTab = getCache(key);
|
||||
// get the tab id from the cookie (already overridden by the target)
|
||||
const cachedTab = getCache(key);
|
||||
if (cachedTab && !emptyArr.includes(cachedTab)) {
|
||||
selectedTab = cachedTab;
|
||||
}
|
||||
|
||||
// Activate panel
|
||||
$('.nav-tabs a[id='+ selectedTab +']').tab('show');
|
||||
|
||||
// When changed save new current tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
setCache(key, $(e.target).attr('id'))
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', (e) => {
|
||||
const newTabId = $(e.target).attr('id');
|
||||
setCache(key, newTabId);
|
||||
});
|
||||
|
||||
// events on tab change
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
var target = $(e.target).attr("href") // activated tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', (e) => {
|
||||
const newTarget = $(e.target).attr("href"); // activated tab
|
||||
});
|
||||
|
||||
hideSpinner();
|
||||
|
||||
}, 50);
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Logs render functionality
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -932,7 +701,7 @@ function toggleAutoRefresh() {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Manages thefilter application
|
||||
// Manages the filter application on the logs
|
||||
function applyFilter() {
|
||||
const filterText = $("#logsFilter").val().toLowerCase();
|
||||
|
||||
@@ -979,7 +748,6 @@ function renderLogs(customData) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Init
|
||||
window.onload = function asyncFooter() {
|
||||
initializeSelectedColumns();
|
||||
renderLogs();
|
||||
|
||||
// initializeTabs();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<h3 class="box-title"><?= lang('Gen_Selected_Devices');?></h3>
|
||||
|
||||
</div>
|
||||
<div class="deviceSelector col-md-9" style="z-index:5"></div>
|
||||
<div class="deviceSelector col-md-9 col-sm-12" style="z-index:5"></div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<button type="button" class="btn btn-default" onclick="markAllSelected()">
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
<!-- NetAlertX -->
|
||||
<script src="js/handle_version.js"></script>
|
||||
<script src="js/ui_components.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||
<script defer src="js/ui_components.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||
|
||||
|
||||
<!-- Select2 JavaScript -->
|
||||
|
||||
@@ -67,14 +67,16 @@ require dirname(__FILE__).'/security.php';
|
||||
<link id="favicon" rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
|
||||
|
||||
<!-- For better UX on Mobile Devices using the Shortcut on the Homescreen -->
|
||||
<link rel="manifest" href="img/manifest.json">
|
||||
<link rel="manifest" href="img/manifest.json" crossorigin="use-credentials">
|
||||
<!-- Dark-Mode Patch -->
|
||||
<?php
|
||||
if ($ENABLED_DARKMODE === True) {
|
||||
echo '<link rel="stylesheet" href="css/dark-patch.css">';
|
||||
$BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/boxed-bg-dark.png\');"';
|
||||
} else { $BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/background.png\');"';}
|
||||
?>
|
||||
|
||||
<?php
|
||||
if ($ENABLED_DARKMODE === True) {
|
||||
echo '<link rel="stylesheet" href="css/dark-patch.css">';
|
||||
$BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/boxed-bg-dark.png\');"';
|
||||
} else { $BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/background.png\');"';}
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Servertime to the right of the hostname -->
|
||||
@@ -312,9 +314,6 @@ if ($ENABLED_DARKMODE === True) {
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu" style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('maintenance.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
|
||||
<li>
|
||||
<a href="maintenance.php#tab_Settings" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_UISettings");?> </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="maintenance.php#tab_DBTools" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_Tools");?> </a>
|
||||
</li>
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "",
|
||||
"Gen_Backup": "",
|
||||
"Gen_Cancel": "",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "",
|
||||
"Gen_DataUpdatedUITakesTime": "",
|
||||
"Gen_Delete": "",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
|
||||
@@ -286,6 +286,7 @@
|
||||
"Gen_AreYouSure": "Sind Sie sich sicher?",
|
||||
"Gen_Backup": "Sichern",
|
||||
"Gen_Cancel": "Abbrechen",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Run",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - It may take a while for the UI to update if a scan is runnig",
|
||||
"Gen_Delete": "Löschen",
|
||||
@@ -611,6 +612,7 @@
|
||||
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.",
|
||||
"Reports_Sent_Log": "Protokoll gesendeter Berichte",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SMTP_FORCE_SSL_description": "Force SSL when connecting to your SMTP server.",
|
||||
"SMTP_FORCE_SSL_name": "Force SSL",
|
||||
"SMTP_PASS_description": "The SMTP server password. ",
|
||||
@@ -723,6 +725,8 @@
|
||||
"UI_PRESENCE_name": "Anzeige im Präsenzdiagramm",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "Automatisch Aktualisieren",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"WEBHOOK_PAYLOAD_description": "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)",
|
||||
"WEBHOOK_PAYLOAD_name": "Payload type",
|
||||
"WEBHOOK_REQUEST_METHOD_description": "The HTTP request method to be used for the webhook call.",
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Are you sure?",
|
||||
"Gen_Backup": "Run Backup",
|
||||
"Gen_Cancel": "Cancel",
|
||||
"Gen_Change": "Change",
|
||||
"Gen_Copy": "Run",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - It may take a while for the UI to update if a scan is running.",
|
||||
"Gen_Delete": "Delete",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.",
|
||||
"Reports_Sent_Log": "Sent Reports Log",
|
||||
"SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) rely on scanning specific network interfaces and subnets. Check the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. <br/> <br/> An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlert<sup>X</sup> having access to the network (UNIFI, dhcp.leases, PiHole, etc.). <br/> <br/> Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.",
|
||||
"SCAN_SUBNETS_name": "Networks to scan",
|
||||
"SYSTEM_TITLE": "System Information",
|
||||
"Setting_Override": "Override value",
|
||||
"Setting_Override_Description": "Enabling this option will override an App supplied default value with the value specified above.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Show in presence chart",
|
||||
"UI_REFRESH_description": "Enter number of seconds after which the UI reloads. Set to <code>0</code> to disable.",
|
||||
"UI_REFRESH_name": "Auto-refresh UI",
|
||||
"VERSION_description": "Version or timestamp helper value to check if app was upgraded.",
|
||||
"VERSION_name": "Version or timestamp",
|
||||
"devices_old": "Refreshing...",
|
||||
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
|
||||
"general_event_title": "Executing an ad-hoc event",
|
||||
|
||||
@@ -284,6 +284,7 @@
|
||||
"Gen_AreYouSure": "¿Estás seguro?",
|
||||
"Gen_Backup": "Ejecutar copia de seguridad",
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Ejecutar",
|
||||
"Gen_DataUpdatedUITakesTime": "Correcto - La interfaz puede tardar en actualizarse si se está ejecutando un escaneo.",
|
||||
"Gen_Delete": "Eliminar",
|
||||
@@ -723,6 +724,8 @@
|
||||
"UI_PRESENCE_name": "Mostrar en el gráfico de presencia",
|
||||
"UI_REFRESH_description": "Ingrese el número de segundos después de los cuales se recarga la interfaz de usuario. Ajustado a <code> 0 </code> para desactivar.",
|
||||
"UI_REFRESH_name": "Actualización automática de la interfaz de usuario",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"WEBHOOK_PAYLOAD_description": "El formato de datos de carga de Webhook para el atributo <code>body</code> > <code>attachments</code> > <code>text</code> en el json de carga. Vea un ejemplo de la carga <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json\">aquí</a>. (por ejemplo: para discord use <code>text</code>)",
|
||||
"WEBHOOK_PAYLOAD_name": "Tipo de carga",
|
||||
"WEBHOOK_REQUEST_METHOD_description": "El método de solicitud HTTP que se utilizará para la llamada de webhook.",
|
||||
@@ -770,4 +773,4 @@
|
||||
"settings_update_item_warning": "Actualice el valor a continuación. Tenga cuidado de seguir el formato anterior. <b>O la validación no se realiza.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Guarda tus cambios antes de probar nuevos ajustes."
|
||||
}
|
||||
}
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Êtes-vous sûr ?",
|
||||
"Gen_Backup": "Lancer la sauvegarde",
|
||||
"Gen_Cancel": "Annuler",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Lancer",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - cela peut prendre du temps à l'interface pour se mettre à jour si un scan est en cours.",
|
||||
"Gen_Delete": "Supprimer",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Détecté automatiquement - indique si l'appareil dispose d'une adresse MAC générée aléatoirement.",
|
||||
"Reports_Sent_Log": "Rapports de log transmis",
|
||||
"SCAN_SUBNETS_description": "La plupart des scanners sur le réseau (scan ARP, NMAP, Nslookup, DIG, Pholud) se base sur le scan d'une partie spécifique des interfaces réseau ou de sous-réseau. Consulter la <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">documentation des sous-réseaux</a> pour plus d'aide sur ce paramètre, notamment pour des VLAN, lesquels sont supportés ou sur comment identifier le masque réseau et votre interface réseau. <br/> <br/> Une alternative à ces scanner sur le réseau et d'activer d'autres scanners d'appareils ou des importe, qui ne dépendent pas du fait de laisser NetAlert<sup>X</sup> accéder au réseau (Unifié, baux DHCP, Pi-hole, etc.).<br/><br/> Remarque : la durée du scan en lui-même dépend du nombre d'adresses IP à scanner, renseignez donc soigneusement avec le bon masque réseau et la bonne interface réseau.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Informations système",
|
||||
"Setting_Override": "Remplacer la valeur",
|
||||
"Setting_Override_Description": "Activer cette option va remplacer la valeur fournie par défaut par une application par la valeur renseignée au-dessus.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Afficher dans le graphique de présence",
|
||||
"UI_REFRESH_description": "Renseignez le nombre de secondes après lequel rafraîchir l'interface graphique. Renseignez <code>0</code> pour désactiver.",
|
||||
"UI_REFRESH_name": "Rafraîchir automatiquement l'interface graphique",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Rafraichissement...",
|
||||
"general_event_description": "L'événement que vous avez lancé peut prendre du temps avant que les tâches de fond ne soit terminées. La durée d'exécution finira une fois que la file d'exécution ci-dessous sera vide (consulter les <a href='/maintenance.php#tab_Logging'>journaux d'erreur</a> si vous rencontrez des erreurs). <br/> <br/> File d'exécution :",
|
||||
"general_event_title": "Lancement d'un événement sur mesure",
|
||||
@@ -690,4 +694,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."
|
||||
}
|
||||
}
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Sei sicuro?",
|
||||
"Gen_Backup": "Esegui backup",
|
||||
"Gen_Cancel": "Annulla",
|
||||
"Gen_Change": "Modifica",
|
||||
"Gen_Copy": "Esegui",
|
||||
"Gen_DataUpdatedUITakesTime": "OK: l'aggiornamento dell'interfaccia utente potrebbe richiedere del tempo se è in esecuzione una scansione.",
|
||||
"Gen_Delete": "Elimina",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Rilevato automaticamente: indica se il dispositivo genera il suo indirizzo MAC casualmente.",
|
||||
"Reports_Sent_Log": "Log rapporti inviati",
|
||||
"SCAN_SUBNETS_description": "La maggior parte degli scanner di rete (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) si basano sulla scansione di interfacce di rete e sottoreti specifiche. Consulta la <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">documentazione sulle sottoreti</a> per assistenza su questa impostazione, in particolare VLAN, quali VLAN sono supportate o come individuare la maschera di rete e l'interfaccia. <br/> <br/> Un'alternativa agli scanner in rete è abilitare altri scanner/importatori di dispositivi che non si affidano a NetAlert<sup>X</sup> che hanno accesso alla rete (UNIFI, dhcp.leases , PiHole, ecc.). <br/> <br/> Nota: il tempo di scansione stesso dipende dal numero di indirizzi IP da controllare, quindi impostalo attentamente con la maschera di rete e l'interfaccia appropriate.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Informazioni sistema",
|
||||
"Setting_Override": "Sovrascrivi valore",
|
||||
"Setting_Override_Description": "L'abilitazione di questa opzione sovrascriverà il valore predefinito fornito dall'app con il valore specificato sopra.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Mostra nel grafico delle presenze",
|
||||
"UI_REFRESH_description": "Inserisci il numero di secondi dopo il quale la UI si ricarica. Imposta a <code>0</code> per disabilitare.",
|
||||
"UI_REFRESH_name": "Aggiorna automaticamente la UI",
|
||||
"VERSION_description": "Valore di supporto della versione o della marca temporale per verificare se l'app è stata aggiornata.",
|
||||
"VERSION_name": "Versione o marca temporale",
|
||||
"devices_old": "Aggiornamento...",
|
||||
"general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:",
|
||||
"general_event_title": "Esecuzione di un evento ad-hoc",
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
// ###################################
|
||||
|
||||
$defaultLang = "en_us";
|
||||
$allLanguages = ["en_us","es_es","de_de", "nb_no", "pl_pl", "pt_br", "ru_ru", "fr_fr", "it_it", "zh_cn", "cs_cz"];
|
||||
$allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "pt_br", "tr_tr", "zh_cn", "cs_cz"];
|
||||
|
||||
|
||||
global $db;
|
||||
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Er du sikker?",
|
||||
"Gen_Backup": "Kjør sikkerhetskopiering",
|
||||
"Gen_Cancel": "Avbryt",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Kjør",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Det kan ta litt tid før brukergrensesnittet oppdateres hvis en skanning kjøres.",
|
||||
"Gen_Delete": "Slett",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Autodetektert - indikerer om enheten randomiserer MAC-adressen sin.",
|
||||
"Reports_Sent_Log": "Sendte rapport logger",
|
||||
"SCAN_SUBNETS_description": "De fleste skannere på nettet (ARP-Scan, NMAP, NSlookup, Dig, Pholus) er avhengige av å skanne spesifikke nettverksgrensesnitt og undernett. Sjekk <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnett dokumentasjonen</a> for hjelp på denne innstillingen, spesielt VLAN-er, hvilke VLAN-er som støttes, eller hvordan du kan finne ut nettverksmasken og grensesnittet ditt. <br/> <br/> Et alternativ til skannere på nettet er å aktivere noen andre enhetsskannere/importører som ikke er avhengige av Netalert<sup>X</sup> med tilgang til nettverket (UniFi, DHCP-Leaser, Pihole, osv.). <br/> <br/> Merk: Selve skanningstiden avhenger av antall IP -adresser som skal sjekkes, så sett dette opp nøye med riktig nettverksmaske og grensesnitt.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Systeminformasjon",
|
||||
"Setting_Override": "Overstyr verdi",
|
||||
"Setting_Override_Description": "Aktivering av dette alternativet vil overstyre en App som leveres standard-verdi med verdien som er spesifisert ovenfor.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Vis i tilstedeværelse-diagrammet",
|
||||
"UI_REFRESH_description": "Skriv inn antall sekunder før UI laster inn på nytt. Sett til <code>0</code> for å deaktivere.",
|
||||
"UI_REFRESH_name": "Oppdater UI automatisk",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Oppdaterer...",
|
||||
"general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:",
|
||||
"general_event_title": "Utfører en ad-hoc hendelse",
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Jesteś pewien?",
|
||||
"Gen_Backup": "Wykonaj Kopie Zapasową",
|
||||
"Gen_Cancel": "Anuluj",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Wykonaj",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Aktualizacja UI może chwile potrwać jeżeli wykonywany jest skan.",
|
||||
"Gen_Delete": "Usuń",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Auto wykrywanie - oznacza czy urządzenie randomizuje swój adres MAC.",
|
||||
"Reports_Sent_Log": "Wyślij zgłoszenie logów",
|
||||
"SCAN_SUBNETS_description": "Większość skanerów sieciowych (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) opiera się na konkretnych interfejsach sieciowych oraz podsieci. Sprawdź <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\"> dokumentacji podsieci</a> jeżeli potrzebujesz pomocy w ustawieniach, a szczególnie z VLAN'ami, jakie VLAN'y są wspierane oraz jak rozgryźć maskę podsieci twojego interfejsu.<br/><br/> Alternatywą do skanerów sieciowych jest uruchomienie innego Skanera Urządzeń/Importera który nie polega by NetAlert<sup>X</sup> miał dostęp do sieci (UNIFI, dhcp.leases, PiHole, itp.).<br/><br/> Notatka: Czas skanu zależy od liczby adresów IP do sprawdzenia, więc ustaw go tak by skanował odpowiedni interfejs i maskę sieciową.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Informacje o Systemie",
|
||||
"Setting_Override": "Nadpisz wartość",
|
||||
"Setting_Override_Description": "Włączanie tej opcji nadpisze podstawową wartość na wartość podaną powyżej.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Pokaż w tabeli obecności",
|
||||
"UI_REFRESH_description": "Wprowadź liczbę sekund po której UI ma się przeładować. Ustaw na <code>0</code> by wyłączyć.",
|
||||
"UI_REFRESH_name": "Automatycznie odświeżaj UI",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Odświeżanie...",
|
||||
"general_event_description": "Wydarzenie które wyzwoliłeś może chwilę zająć dopóki procesy w tle nie zakończą się. Wykonanie zakończy się kiedy kolejka się opróżni (Sprawdź <a href='/maintenance.php#tab_Logging'>logi błędów</a> jeżeli napotkasz błędy).<br/><br/> Kolejka wykonywania:",
|
||||
"general_event_title": "Wykonywanie wydarzeń ad-hoc",
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Tem certeza?",
|
||||
"Gen_Backup": "Executar backup",
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Executar",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Pode levar um tempo para a interface do usuário ser atualizada se uma verificação estiver em execução.",
|
||||
"Gen_Delete": "Excluir",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Вы уверены?",
|
||||
"Gen_Backup": "Запустить резервное копирование",
|
||||
"Gen_Cancel": "Отмена",
|
||||
"Gen_Change": "Изменить",
|
||||
"Gen_Copy": "Запустить",
|
||||
"Gen_DataUpdatedUITakesTime": "ОК - Обновление UI может занять некоторое время, если сканирование выполняется.",
|
||||
"Gen_Delete": "Удалить",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "Автоматически обнаружено — указывает, рандомизирует ли устройство свой MAC-адрес.",
|
||||
"Reports_Sent_Log": "Отправить журнал логов",
|
||||
"SCAN_SUBNETS_description": "Большинство сетевых сканеров (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) полагаются на сканирование определенных сетевых интерфейсов и подсетей. Дополнительную информацию по этому параметру можно найти в <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">документации по подсетям</a>, особенно VLAN, какие VLAN поддерживаются или как разобраться в маске сети и своем интерфейсе. <br/> <br/> Альтернативой сетевым сканерам является включение некоторых других сканеров/импортеров устройств, которые не полагаются на NetAlert<sup>X</sup>, имеющий доступ к сети (UNIFI, dhcp.leases , PiHole и др.). <br/> <br/> Примечание. Само время сканирования зависит от количества проверяемых IP-адресов, поэтому тщательно настройте его, указав соответствующую маску сети и интерфейс.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Системная информация",
|
||||
"Setting_Override": "Переопределить значение",
|
||||
"Setting_Override_Description": "Включение этой опции приведет к переопределению значения по умолчанию, предоставленного приложением, на значение, указанное выше.",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "Показать в диаграмме присутствия",
|
||||
"UI_REFRESH_description": "Введите количество секунд, по истечении которых пользовательский интерфейс перезагружается. Установите значение <code>0</code>, чтобы отключить.",
|
||||
"UI_REFRESH_name": "Автоматическое обновление интерфейса",
|
||||
"VERSION_description": "Вспомогательное значение версии или метки времени, позволяющее проверить, было ли приложение обновлено.",
|
||||
"VERSION_name": "Версия или временная метка",
|
||||
"devices_old": "Актуализируется...",
|
||||
"general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:",
|
||||
"general_event_title": "Выполнение специального события",
|
||||
@@ -690,4 +694,4 @@
|
||||
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
|
||||
}
|
||||
}
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "Emin misiniz?",
|
||||
"Gen_Backup": "",
|
||||
"Gen_Cancel": "İptal",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Çalıştır",
|
||||
"Gen_DataUpdatedUITakesTime": "TAMAM - Eğer bir tarama çalışıyorsa arayüzün güncellenmesi biraz zaman alabilir",
|
||||
"Gen_Delete": "Sil",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Yenileniyor...",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
"Gen_AreYouSure": "你确定吗?",
|
||||
"Gen_Backup": "运行备份",
|
||||
"Gen_Cancel": "取消",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "运行",
|
||||
"Gen_DataUpdatedUITakesTime": "好的 - 如果扫描正在运行,UI 可能需要一段时间才能更新。",
|
||||
"Gen_Delete": "删除",
|
||||
@@ -556,6 +557,7 @@
|
||||
"RandomMAC_hover": "自动检测 - 表示设备是否随机化其 MAC 地址。",
|
||||
"Reports_Sent_Log": "已发送报告日志",
|
||||
"SCAN_SUBNETS_description": "大多数网络扫描器(ARP-SCAN、NMAP、NSLOOKUP、DIG、PHOLUS)依赖于扫描特定的网络接口和子网。查看<a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">子网文档</a>以获取有关此设置的帮助,尤其是 VLAN、支持哪些 VLAN,或者如何确定网络掩码和接口。<br/> <br/> 网络扫描器的替代方法是启用一些其他不依赖于 NetAlert<sup>X</sup> 访问网络的设备扫描器/导入器(UNIFI、dhcp.leases、PiHole 等)。<br/> <br/> 注意:扫描时间本身取决于要检查的 IP 地址数量,因此请使用适当的网络掩码和接口仔细设置。",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "系统信息",
|
||||
"Setting_Override": "覆盖值",
|
||||
"Setting_Override_Description": "启用此选项将用上面指定的值覆盖应用程序提供的默认值。",
|
||||
@@ -654,6 +656,8 @@
|
||||
"UI_PRESENCE_name": "在存在图表中显示",
|
||||
"UI_REFRESH_description": "输入界面重新加载的秒数。设置为 <code>0</code> 可禁用。",
|
||||
"UI_REFRESH_name": "自动刷新界面",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "刷新中...",
|
||||
"general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:",
|
||||
"general_event_title": "执行自组织网络事件",
|
||||
@@ -690,4 +694,4 @@
|
||||
"settings_update_item_warning": "更新下面的值。请注意遵循先前的格式。<b>未执行验证。</b>",
|
||||
"test_event_icon": "",
|
||||
"test_event_tooltip": "在测试设置之前,请先保存更改。"
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
// ## GUI settings processing start
|
||||
// ###################################
|
||||
|
||||
if( isset($_COOKIE['Front_Dark_Mode_Enabled']))
|
||||
if( isset($_COOKIE['UI_dark_mode']))
|
||||
{
|
||||
$ENABLED_DARKMODE = $_COOKIE['Front_Dark_Mode_Enabled'] == "true";
|
||||
$ENABLED_DARKMODE = $_COOKIE['UI_dark_mode'] == "True";
|
||||
}else
|
||||
{
|
||||
$ENABLED_DARKMODE = False;
|
||||
|
||||
@@ -11,12 +11,12 @@ NetAlertX supports additional plugins to extend its functionality, each with its
|
||||
> You can load additional Plugins via the General -> `LOADED_PLUGINS` setting. Use `Ctrl + Click` to select/deselect.
|
||||
|
||||
1. Pick your `🔍 dev scanner` plugin (e.g. `ARPSCAN` or `NMAPDEV`), or import devices into the application with an `📥 importer` plugin. (See **✅Enabling plugins** below)
|
||||
1. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
||||
1. Setup your [Network topology diagram](/docs/NETWORK_TREE.md)
|
||||
1. Fine-tune [Notifications](/docs/NOTIFICATIONS.md)
|
||||
1. [Backup your setup](/docs/BACKUPS.md)
|
||||
1. Contribute and [Create custom plugins](/docs/PLUGINS_DEV.md)
|
||||
1. Consider [donating](https://github.com/jokob-sk/NetAlertX?tab=readme-ov-file#-sponsors) to keep me going
|
||||
2. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
||||
3. Setup your [Network topology diagram](/docs/NETWORK_TREE.md)
|
||||
4. Fine-tune [Notifications](/docs/NOTIFICATIONS.md)
|
||||
5. [Backup your setup](/docs/BACKUPS.md)
|
||||
6. Contribute and [Create custom plugins](/docs/PLUGINS_DEV.md)
|
||||
7. Consider [donating](https://github.com/jokob-sk/NetAlertX?tab=readme-ov-file#-sponsors) to keep me going
|
||||
|
||||
|
||||
## 📑 Available Plugins
|
||||
@@ -53,6 +53,7 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T
|
||||
| `SMTP` | ▶️ | Email notifications | | | Script | [_publisher_email](/front/plugins/_publisher_email/) |
|
||||
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | | Script | [snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| `SYNC` | 🔍/⚙/📥| Sync & import from NetAlertX instances | 🖧 🔄 | | Script | [sync](/front/plugins/sync/) |
|
||||
| `TELEGRAM` | ▶️ | Telegram notifications | | | Script | [_publisher_telegram](/front/plugins/_publisher_telegram/) |
|
||||
| `UNDIS` | 🔍/📥 | Create dummy devices | | | Script | [undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| `UNFIMP` | 🔍/📥 | UniFi device import & sync | 🖧 | | Script | [unifi_import](/front/plugins/unifi_import/) |
|
||||
| `VNDRPDT` | ⚙ | Vendor database update | | | Script | [vendor_update](/front/plugins/vendor_update/) |
|
||||
|
||||
10
front/plugins/_publisher_telegram/README.md
Executable file
10
front/plugins/_publisher_telegram/README.md
Executable file
@@ -0,0 +1,10 @@
|
||||
## Overview
|
||||
|
||||
You can send notifications via Telegram
|
||||
## Notes
|
||||
|
||||
You need Telegram bot to send notifications
|
||||
|
||||
### Usage
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
470
front/plugins/_publisher_telegram/config.json
Executable file
470
front/plugins/_publisher_telegram/config.json
Executable file
@@ -0,0 +1,470 @@
|
||||
{
|
||||
"code_name": "_publisher_telegram",
|
||||
"unique_prefix": "TELEGRAM",
|
||||
"plugin_type": "publisher",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram publisher"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "<i class=\"fa-solid fa-bullhorn\"></i>"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to publish a notification via Telegram."
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"database_column_definitions": [
|
||||
{
|
||||
"column": "Index",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Plugin",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_PrimaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "url",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_SecondaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeCreated",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Sent when"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeChanged",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Changed"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cambiado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value1",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "eval",
|
||||
"default_value": "",
|
||||
"options": [
|
||||
{
|
||||
"type": "eval",
|
||||
"param": "`<a href='/report.php?guid=${value}'>${value}</a>`"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Notification GUID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"css_classes": "col-sm-8",
|
||||
"show": true,
|
||||
"type": "textarea_readonly",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Result"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value3",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value4",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "UserData",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "textbox_save",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Comments"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comentarios"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Status",
|
||||
"css_classes": "col-sm-1",
|
||||
"show": false,
|
||||
"type": "replace",
|
||||
"default_value": "",
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "missing-in-last-scan",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Status"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Estado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Extra",
|
||||
"css_classes": "col-sm-3",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Extra"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Extra"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"function": "RUN",
|
||||
"events": ["test"],
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "select", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "disabled",
|
||||
"options": ["disabled", "on_notification"],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "When to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cuando ejecuta"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enable sending notifications via a Telegram messanger"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "readonly": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": "python3 /app/front/plugins/_publisher_telegram/tg.py",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando a ejecutar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 10,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Run timeout"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo de espera de ejecución"
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string": "Wartezeit"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "HOST",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "input", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram chat id"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram chat id. If you want to send messages to user, paste user id (Example: <code>1234123412</code>)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "URL",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "input", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram bot token"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram bot token. You cat get at from <a target=\"_blank\" href=\"https://t.me/BotFather\">BotFather</a>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "SIZE",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 1024,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Max payload size"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tamaño máximo de carga útil"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The maximum size of the payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
124
front/plugins/_publisher_telegram/tg.py
Executable file
124
front/plugins/_publisher_telegram/tg.py
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH = "/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
import conf
|
||||
from const import confFileName
|
||||
from plugin_helper import Plugin_Objects
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
from pytz import timezone
|
||||
|
||||
# Make sure the TIMEZONE for logging is correct
|
||||
conf.tz = timezone(get_setting_value('TIMEZONE'))
|
||||
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
|
||||
pluginName = 'TELEGRAM'
|
||||
|
||||
|
||||
def main():
|
||||
mylog('verbose', [f'[{pluginName}](publisher) In script'])
|
||||
|
||||
# Check if basic config settings supplied
|
||||
if check_config() == False:
|
||||
mylog('none', [
|
||||
f'[{pluginName}] ⚠ ERROR: Publisher notification gateway not set up correctly. Check your {confFileName} {pluginName}_* variables.'])
|
||||
return
|
||||
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Notification_obj instance
|
||||
notifications = Notification_obj(db)
|
||||
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
# Send notification
|
||||
result = send(notification["Text"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
primaryId=pluginName,
|
||||
secondaryId=timeNowTZ(),
|
||||
watched1=notification["GUID"],
|
||||
watched2=result,
|
||||
watched3='null',
|
||||
watched4='null',
|
||||
extra='null',
|
||||
foreignKey=notification["GUID"]
|
||||
)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
return True
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
def send(text):
|
||||
# limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB)
|
||||
limit = get_setting_value('TELEGRAM_SIZE')
|
||||
|
||||
if len(text) > limit:
|
||||
payloadData = text[:limit] + " (text was truncated)"
|
||||
else:
|
||||
payloadData = text
|
||||
|
||||
try:
|
||||
# try runnning a subprocess
|
||||
|
||||
req = """curl --location 'https://api.telegram.org/bot%s/sendMessage' \\
|
||||
--header 'Content-Type: application/json' \\
|
||||
--data '{
|
||||
"chat_id": "%s",
|
||||
"text": "%s",
|
||||
"disable_notification": false
|
||||
}'""" % (get_setting_value('TELEGRAM_URL'), get_setting_value('TELEGRAM_HOST'), payloadData)
|
||||
|
||||
mylog('debug', [req])
|
||||
|
||||
p = subprocess.Popen(req, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
# write stdout and stderr into .log files for debugging if needed
|
||||
# Log the stdout and stderr
|
||||
mylog('debug', [stdout, stderr])
|
||||
|
||||
# log result
|
||||
result = stdout
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occurred, handle it
|
||||
mylog('none', [e.output])
|
||||
|
||||
# log result
|
||||
result = e.output
|
||||
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -147,8 +147,9 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
# 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)'])
|
||||
cursor.execute (f"""DELETE FROM Devices
|
||||
WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""")
|
||||
query = f"""DELETE FROM Devices WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '-{str(HRS_TO_KEEP_NEWDEV)} hour')"""
|
||||
mylog('verbose', [f'[{pluginName}] Query: {query} '])
|
||||
cursor.execute (query)
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup Pholus_Scan
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"code_name": "mikrotik_scan",
|
||||
"unique_prefix": "MTSCAN",
|
||||
"plugin_type": "other",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_4",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
@@ -11,7 +11,7 @@
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Mikrotik (Name discovery)"
|
||||
"string": "Mikrotik (Device discovery)"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
@@ -23,7 +23,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to discover device names."
|
||||
"string": "A plugin to discover devices via Mikrotik."
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# test script by running:
|
||||
# tbc
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
@@ -40,42 +38,35 @@ pluginName = 'MTSCAN'
|
||||
|
||||
def main():
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
|
||||
mt_host = get_setting_value('MTSCAN_MT_HOST')
|
||||
mt_port = get_setting_value('MTSCAN_MT_PORT')
|
||||
mt_user = get_setting_value('MTSCAN_MT_USER')
|
||||
mt_password = get_setting_value('MTSCAN_MT_PASS')
|
||||
|
||||
#mylog('verbose', [f'[{pluginName}] Router: {mt_host}:{mt_port} user: {mt_user}, pass: {mt_password}'])
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
# init global variables
|
||||
global MT_HOST, MT_PORT, MT_USER, MT_PASS
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Device_obj instance
|
||||
device_handler = Device_obj(db)
|
||||
# Mikrotik settings
|
||||
MT_HOST = get_setting_value('MTSCAN_MT_HOST')
|
||||
MT_PORT = get_setting_value('MTSCAN_MT_PORT')
|
||||
MT_USER = get_setting_value('MTSCAN_MT_USER')
|
||||
MT_PASS = get_setting_value('MTSCAN_MT_PASS')
|
||||
|
||||
# Retrieve devices
|
||||
#unknown_devices = device_handler.getUnknown()
|
||||
#mylog('verbose', [f'[{pluginName}] Unknown devices count: {len(unknown_devices)}'])
|
||||
plugin_objects = get_entries(plugin_objects)
|
||||
|
||||
all_devices = device_handler.getAll()
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Scan finished, found {len(plugin_objects)} devices'])
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] all devices count: {len(all_devices)}'])
|
||||
|
||||
device_map = {d['dev_MAC']:d['dev_LastIP'] for d in all_devices}
|
||||
def get_entries(plugin_objects: Plugin_Objects) -> Plugin_Objects:
|
||||
|
||||
try:
|
||||
# connect router
|
||||
api = connect(username=mt_user, password=mt_password, host=mt_host, port=mt_port)
|
||||
api = connect(username=MT_USER, password=MT_PASS, host=MT_HOST, port=MT_PORT)
|
||||
|
||||
# get dhcp leases
|
||||
leases = api('/ip/dhcp-server/lease/print')
|
||||
|
||||
|
||||
|
||||
for lease in leases:
|
||||
lease_id = lease.get('.id')
|
||||
@@ -84,56 +75,31 @@ def main():
|
||||
host_name = lease.get('host-name')
|
||||
comment = lease.get('comment')
|
||||
last_seen = lease.get('last-seen')
|
||||
status = lease.get('status')
|
||||
|
||||
mylog('verbose', [f"ID: {lease_id}, Address: {address}, MAC Address: {mac_address}, Host Name: {host_name}, Comment: {comment}, Last Seen: {last_seen}"])
|
||||
if mac_address in device_map.keys():
|
||||
device_name = host_name
|
||||
if comment != '':
|
||||
device_name = comment
|
||||
|
||||
mylog('verbose', [f"ID: {lease_id}, Address: {address}, MAC Address: {mac_address}, Host Name: {host_name}, Comment: {comment}, Last Seen: {last_seen}, Status: {status}"])
|
||||
|
||||
if (status == "bound"):
|
||||
plugin_objects.add_object(
|
||||
# "Name-MAC", "LastIP", "IP", "Name","Host","LastSeen","Comment"
|
||||
primaryId = mac_address,
|
||||
secondaryId = device_map[mac_address],
|
||||
secondaryId = '',
|
||||
watched1 = address,
|
||||
watched2 = device_name,
|
||||
watched3 = host_name,
|
||||
watched4 = last_seen,
|
||||
watched2 = host_name,
|
||||
watched3 = last_seen,
|
||||
watched4 = '',
|
||||
extra = '',
|
||||
helpVal1 = comment,
|
||||
foreignKey = mac_address)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
except TrapError as e:
|
||||
mylog('error', [f"An error occurred: {e}"])
|
||||
except Exception as e:
|
||||
mylog('error', [f"Failed to connect to MikroTik API: {e}"])
|
||||
|
||||
|
||||
#for device in unknown_devices:
|
||||
# domain_name, dns_server = execute_nslookup(device['dev_LastIP'], timeout)
|
||||
|
||||
# if domain_name != '':
|
||||
# plugin_objects.add_object(
|
||||
# # "MAC", "IP", "Server", "Name"
|
||||
# primaryId = device['dev_MAC'],
|
||||
# secondaryId = device['dev_LastIP'],
|
||||
# watched1 = dns_server,
|
||||
# watched2 = domain_name,
|
||||
# watched3 = '',
|
||||
# watched4 = '',
|
||||
# extra = '',
|
||||
# foreignKey = device['dev_MAC'])
|
||||
|
||||
#plugin_objects.write_result_file()
|
||||
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Script finished'])
|
||||
|
||||
return 0
|
||||
return plugin_objects
|
||||
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# BEGIN
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NMAP-scan is a command-line tool to discover and fingerprint IP hosts on the local network. The NMAP-scan (and other Network-scan plugin times using the `SCAN_SUBNETS` setting) time depends on the number of IP addresses to check so set this up carefully with the appropriate network mask and interface. Check the [subnets documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) for help with setting up VLANs, what VLANs are supported, or how to figure out the network mask and your interface.
|
||||
|
||||
> [!NOTE]
|
||||
> The `NMAPDEV` plugin is great for detecting the availability of devices, however ARP scan might be better covering multiple VLANS. You can always combine different scan methods. You can find all available network scanning options (marked as `🔍 dev scanner`) in the [Plugins overview](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) readme.
|
||||
> The `NMAPDEV` plugin is great for detecting the availability of devices, however ARP scan might be better covering multiple VLANS and subnets as NMAP can't pickup the MAC address from other subnets (this is an NMAP limitation) which are necessary to identify a device. You can always combine different scan methods. You can find all available network scanning options (marked as `🔍 dev scanner`) in the [Plugins overview](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) readme.
|
||||
|
||||
### Usage
|
||||
|
||||
|
||||
@@ -26,6 +26,275 @@
|
||||
],
|
||||
"params": [],
|
||||
"settings": [
|
||||
{
|
||||
"function": "NOT_RANDOM_MAC",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [
|
||||
{ "placeholder": "Enter value" },
|
||||
{ "suffix": "_in" },
|
||||
{ "cssClasses": "col-sm-10" },
|
||||
{ "prefillValue": "null" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this,false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "multiple": "true" },
|
||||
{ "readonly": "true" },
|
||||
{ "editable": "true" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [],
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "ICONS",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [
|
||||
{ "placeholder": "Enter value" },
|
||||
{ "suffix": "_in" },
|
||||
{ "cssClasses": "col-sm-10" },
|
||||
{ "prefillValue": "null" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this,false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "multiple": "true" },
|
||||
{ "readonly": "true" },
|
||||
{ "editable": "true" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [
|
||||
"PGkgY2xhc3M9J2ZhIGZhLXdpZmknPjwvaT4=",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4",
|
||||
"PGkgY2xhc3M9J2ZhIGZhLWdhbWVwYWQnPjwvaT4"
|
||||
],
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "REFRESH",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": 0,
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "DEV_SECTIONS",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [],
|
||||
"options": ["Tile Cards", "Device Presence"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "PRESENCE",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": ["online", "offline", "archived"],
|
||||
"options": ["online", "offline", "archived"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "MY_DEVICES",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": ["online", "offline", "archived", "new", "down"],
|
||||
"options": ["online", "offline", "archived", "new", "down"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "device_columns",
|
||||
"type": {
|
||||
@@ -34,43 +303,76 @@
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true", "ordeable": "true" }],
|
||||
"transformers": ["getString"]
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "selectAll(this)" },
|
||||
{ "getStringKey": "Gen_Add_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "unselectAll(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "selectChange(this)" },
|
||||
{ "getStringKey": "Gen_Change" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [
|
||||
"getString-Device_TableHead_Icon-value-3",
|
||||
"getString-Device_TableHead_Name-value-0",
|
||||
"getString-Device_TableHead_Type-value-2",
|
||||
"getString-Device_TableHead_LastIP-value-8",
|
||||
"getString-Device_TableHead_Status-value-10",
|
||||
"getString-Device_TableHead_MAC_full-value-11"
|
||||
"Device_TableHead_Icon",
|
||||
"Device_TableHead_Name",
|
||||
"Device_TableHead_Type",
|
||||
"Device_TableHead_LastIP",
|
||||
"Device_TableHead_Status",
|
||||
"Device_TableHead_MAC_full"
|
||||
],
|
||||
"options": [
|
||||
"getString-Device_TableHead_Name-value-0",
|
||||
"getString-Device_TableHead_Owner-value-1",
|
||||
"getString-Device_TableHead_Type-value-2",
|
||||
"getString-Device_TableHead_Icon-value-3",
|
||||
"getString-Device_TableHead_Favorite-value-4",
|
||||
"getString-Device_TableHead_Group-value-5",
|
||||
"getString-Device_TableHead_FirstSession-value-6",
|
||||
"getString-Device_TableHead_LastSession-value-7",
|
||||
"getString-Device_TableHead_LastIP-value-8",
|
||||
"getString-Device_TableHead_MAC-value-9",
|
||||
"getString-Device_TableHead_Status-value-10",
|
||||
"getString-Device_TableHead_MAC_full-value-11",
|
||||
"getString-Device_TableHead_LastIPOrder-value-12",
|
||||
"getString-Device_TableHead_Rowid-value-13",
|
||||
"getString-Device_TableHead_Parent_MAC-value-14",
|
||||
"getString-Device_TableHead_Connected_Devices-value-15",
|
||||
"getString-Device_TableHead_Location-value-16",
|
||||
"getString-Device_TableHead_Vendor-value-17",
|
||||
"getString-Device_TableHead_Port-value-18",
|
||||
"getString-Device_TableHead_GUID-value-19",
|
||||
"getString-Device_TableHead_SyncHubNodeName-value-20",
|
||||
"getString-Device_TableHead_NetworkSite-value-21",
|
||||
"getString-Device_TableHead_SSID-value-22"
|
||||
"Device_TableHead_Name",
|
||||
"Device_TableHead_Owner",
|
||||
"Device_TableHead_Type",
|
||||
"Device_TableHead_Icon",
|
||||
"Device_TableHead_Favorite",
|
||||
"Device_TableHead_Group",
|
||||
"Device_TableHead_FirstSession",
|
||||
"Device_TableHead_LastSession",
|
||||
"Device_TableHead_LastIP",
|
||||
"Device_TableHead_MAC",
|
||||
"Device_TableHead_Status",
|
||||
"Device_TableHead_MAC_full",
|
||||
"Device_TableHead_LastIPOrder",
|
||||
"Device_TableHead_Rowid",
|
||||
"Device_TableHead_Parent_MAC",
|
||||
"Device_TableHead_Connected_Devices",
|
||||
"Device_TableHead_Location",
|
||||
"Device_TableHead_Vendor",
|
||||
"Device_TableHead_Port",
|
||||
"Device_TableHead_GUID",
|
||||
"Device_TableHead_SyncHubNodeName",
|
||||
"Device_TableHead_NetworkSite",
|
||||
"Device_TableHead_SSID"
|
||||
],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
@@ -82,7 +384,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Which columns to show on the Devices page."
|
||||
"string": "Columns and their order that are shown on the Devices page. Drag and drop the order of columns, click <code>x</code> to remove columns. You can also click into the field to selectivelly add fields."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -158,6 +460,34 @@
|
||||
"string": "Hide Device tiles with zero results."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "dark_mode",
|
||||
"type": {
|
||||
"dataType": "boolean",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "checkbox" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": false,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Dark mode"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enable dark mode."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
});
|
||||
|
||||
// EVENTS
|
||||
// process events (e.g. run ascan, or test a notification) if associated with the setting
|
||||
// process events (e.g. run a scan, or test a notification) if associated with the setting
|
||||
let eventsHtml = "";
|
||||
|
||||
const eventsList = createArray(set['Events']);
|
||||
@@ -591,6 +591,8 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
}, 50);
|
||||
|
||||
setupSmoothScrolling()
|
||||
// try to initialize select2
|
||||
initSelect2()
|
||||
hideSpinner()
|
||||
|
||||
}
|
||||
@@ -669,26 +671,34 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
value = applyTransformers(value, transformers);
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (inputType === 'checkbox') {
|
||||
} else if (dataType === 'boolean') {
|
||||
|
||||
value = $(`#${setCodeName}`).is(':checked') ? 1 : 0;
|
||||
value = applyTransformers(value, transformers);
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (dataType === "array" ) {
|
||||
|
||||
// make sure to collect all if set as "editable" or selected only otherwise
|
||||
$(`#${setCodeName}`).attr("my-editable") == "true" ? additionalSelector = "" : additionalSelector = ":selected"
|
||||
|
||||
const temps = [];
|
||||
$(`#${setCodeName} option${additionalSelector}`).each(function() {
|
||||
const vl = $(this).val();
|
||||
if (vl !== '') {
|
||||
temps.push(applyTransformers(vl, transformers));
|
||||
}
|
||||
});
|
||||
let temps = [];
|
||||
|
||||
if(isOrdeable)
|
||||
{
|
||||
temps = $(`#${setCodeName}`).val()
|
||||
} else
|
||||
{
|
||||
// make sure to collect all if set as "editable" or selected only otherwise
|
||||
$(`#${setCodeName}`).attr("my-editable") == "true" ? additionalSelector = "" : additionalSelector = ":selected";
|
||||
|
||||
$(`#${setCodeName} option${additionalSelector}`).each(function() {
|
||||
const vl = $(this).val();
|
||||
if (vl !== '') {
|
||||
temps.push(applyTransformers(vl, transformers));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
value = JSON.stringify(temps);
|
||||
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (dataType === "json") {
|
||||
@@ -784,35 +794,34 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
setTimeout("handleLoadingDialog()", 1000);
|
||||
|
||||
} else
|
||||
{
|
||||
// check if the app is initialized and hide the spinner
|
||||
if(isAppInitialized())
|
||||
{
|
||||
// init page
|
||||
getData()
|
||||
|
||||
// reload page if outdated information might be displayed
|
||||
if(secondsSincePageLoad() > 5)
|
||||
{
|
||||
clearCache()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("isAppInitialized() returned false, reloading in 3s");
|
||||
// reload the page if not initialized to give time the background tasks to finish
|
||||
setTimeout(() => {
|
||||
|
||||
window.location.reload()
|
||||
|
||||
}, 3000);
|
||||
}
|
||||
{
|
||||
checkInitialization();
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('lastImportedTime').innerHTML = humanReadable;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function checkInitialization() {
|
||||
if (isAppInitialized()) {
|
||||
// App is initialized, hide spinner and proceed with initialization
|
||||
console.log("App initialized, proceeding...");
|
||||
getData();
|
||||
|
||||
// Reload page if outdated information might be displayed
|
||||
if (secondsSincePageLoad() > 10) {
|
||||
clearCache();
|
||||
}
|
||||
} else {
|
||||
console.log("App not initialized, checking again in 1s...");
|
||||
|
||||
// Check again after a delay
|
||||
setTimeout(checkInitialization, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
showSpinner()
|
||||
|
||||
@@ -15,6 +15,7 @@ pluginsPath = applicationPath + '/front/plugins'
|
||||
logPath = applicationPath + '/front/log'
|
||||
apiPath = applicationPath + '/front/api/'
|
||||
reportTemplatesPath = applicationPath + '/front/report_templates/'
|
||||
fullConfFolder = applicationPath + '/config'
|
||||
fullConfPath = applicationPath + confPath
|
||||
fullDbPath = applicationPath + dbPath
|
||||
vendorsPath = '/usr/share/arp-scan/ieee-oui.txt'
|
||||
|
||||
@@ -11,13 +11,14 @@ import re
|
||||
|
||||
|
||||
import conf
|
||||
from const import fullConfPath
|
||||
from helper import collect_lang_strings, updateSubnets, initOrSetParam, isJsonObject, updateState, setting_value_to_python_type
|
||||
from const import fullConfPath, applicationPath, fullConfFolder
|
||||
from helper import collect_lang_strings, updateSubnets, initOrSetParam, isJsonObject, updateState, setting_value_to_python_type, timeNowTZ, get_setting_value
|
||||
from logger import mylog
|
||||
from api import update_api
|
||||
from scheduler import schedule_class
|
||||
from plugin import print_plugin_info, run_plugin_scripts
|
||||
from plugin_utils import get_plugins_configs, get_plugin_setting_obj
|
||||
from notification import write_notification
|
||||
|
||||
#===============================================================================
|
||||
# Initialise user defined values
|
||||
@@ -28,7 +29,8 @@ from plugin_utils import get_plugins_configs, get_plugin_setting_obj
|
||||
# Check config dictionary
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None):
|
||||
# managing application settings, ensuring SQL safety for user input, and updating internal configuration lists
|
||||
def ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False):
|
||||
if events is None:
|
||||
events = []
|
||||
if setJsonMetadata is None:
|
||||
@@ -40,7 +42,7 @@ def ccd(key, default, config_dir, name, inputtype, options, group, events=None,
|
||||
result = default
|
||||
|
||||
# Use existing value if already supplied, otherwise default value is used
|
||||
if key in config_dir:
|
||||
if forceDefault == False and key in config_dir:
|
||||
result = config_dir[key]
|
||||
|
||||
# Single quotes might break SQL queries, replacing them
|
||||
@@ -69,16 +71,20 @@ def update_or_append(settings_list, item_tuple, key):
|
||||
if settings_list is None:
|
||||
settings_list = []
|
||||
|
||||
# mylog('debug', ['[Import Config] update_or_append debug '])
|
||||
# mylog('debug', ['[Import Config] update_or_append ', settings_list])
|
||||
# mylog('debug', ['[Import Config] update_or_append item_tuple ' , item_tuple])
|
||||
|
||||
for index, item in enumerate(settings_list):
|
||||
if item[0] == key:
|
||||
settings_list[index] = item_tuple
|
||||
mylog('debug', ['[Import Config] FOUND key : ', key])
|
||||
return settings_list
|
||||
mylog('trace', ['[Import Config] OLD TUPLE : ', item])
|
||||
# Keep values marked as "_KEEP_"
|
||||
updated_tuple = tuple(
|
||||
new_val if new_val != "_KEEP_" else old_val
|
||||
for old_val, new_val in zip(item, item_tuple)
|
||||
)
|
||||
mylog('trace', ['[Import Config] NEW TUPLE : ', updated_tuple])
|
||||
settings_list[index] = updated_tuple
|
||||
mylog('trace', ['[Import Config] FOUND key : ', key])
|
||||
return settings_list
|
||||
|
||||
|
||||
settings_list.append(item_tuple)
|
||||
return settings_list
|
||||
|
||||
@@ -140,16 +146,11 @@ def importConfigs (db, all_plugins):
|
||||
conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'General')
|
||||
conf.API_CUSTOM_SQL = ccd('API_CUSTOM_SQL', 'SELECT * FROM Devices WHERE dev_PresentLastScan = 0' , c_d, 'Custom endpoint', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.VERSION = ccd('VERSION', '' , c_d, 'Version', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [{ "readonly": "true" }] ,"transformers": []}]}', '', 'General')
|
||||
conf.NETWORK_DEVICE_TYPES = ccd('NETWORK_DEVICE_TYPES', ['AP', 'Gateway', 'Firewall', 'Hypervisor', 'Powerline', 'Switch', 'WLAN', 'PLC', 'Router','USB LAN Adapter', 'USB WIFI Adapter', 'Internet'] , c_d, 'Network device types', '{"dataType":"array","elements":[{"elementType":"input","elementOptions":[{"placeholder":"Enter value"},{"suffix":"_in"},{"cssClasses":"col-sm-10"},{"prefillValue":"null"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":["_in"]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"addList(this,false)"},{"getStringKey":"Gen_Add"}],"transformers":[]},{"elementType":"select", "elementHasInputValue":1,"elementOptions":[{"multiple":"true"},{"readonly":"true"},{"editable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeAllOptions(this)"},{"getStringKey":"Gen_Remove_All"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeFromList(this)"},{"getStringKey":"Gen_Remove_Last"}],"transformers":[]}]}', '[]', 'General')
|
||||
|
||||
# UI
|
||||
conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian (it_it)', 'Portuguese (pt_br)', 'Polish (pl_pl)', 'Turkish (tr_tr)', 'Chinese (zh_cn)', 'Czech (cs_cz)' ]", 'UI')
|
||||
conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "suffix": "_in" },{ "cssClasses": "col-sm-10" },{ "prefillValue": "null" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": ["_in"] },{ "separator": "" },{ "cssClasses": "col-xs-12" },{ "onClick": "addList(this, false)" },{ "getStringKey": "Gen_Add" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeAllOptions(this)" },{ "getStringKey": "Gen_Remove_All" }],"transformers": []},{"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeFromList(this)" },{ "getStringKey": "Gen_Remove_Last" }],"transformers": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9J2ZhIGZhLXdpZmknPjwvaT4=', 'PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4', 'PGkgY2xhc3M9J2ZhIGZhLWdhbWVwYWQnPjwvaT4'] , c_d, 'Icons', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "suffix": "_in" },{ "cssClasses": "col-sm-10" },{ "prefillValue": "null" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": ["_in"] },{ "separator": "" },{ "cssClasses": "col-xs-12" },{ "onClick": "addList(this, false)" },{ "getStringKey": "Gen_Add" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeAllOptions(this)" },{ "getStringKey": "Gen_Remove_All" }],"transformers": []},{"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeFromList(this)" },{ "getStringKey": "Gen_Remove_Last" }],"transformers": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_REFRESH = ccd('UI_REFRESH', 0 , c_d, 'Refresh interval', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'UI')
|
||||
conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['Tile Cards', 'Device Presence']", 'UI')
|
||||
conf.UI_PRESENCE = ccd('UI_PRESENCE', ['online', 'offline', 'archived'] , c_d, 'Include in presence', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['online', 'offline', 'archived']", 'UI')
|
||||
conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['online', 'offline', 'archived', 'new', 'down']", 'UI')
|
||||
conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian (it_it)', 'Portuguese (pt_br)', 'Polish (pl_pl)', 'Turkish (tr_tr)', 'Chinese (zh_cn)', 'Czech (cs_cz)' ]", 'UI')
|
||||
|
||||
# Init timezone in case it changed
|
||||
conf.tz = timezone(conf.TIMEZONE)
|
||||
@@ -285,8 +286,7 @@ def importConfigs (db, all_plugins):
|
||||
for plugin in all_plugins:
|
||||
pref = plugin["unique_prefix"]
|
||||
loaded_plugins_prefixes.append(pref)
|
||||
|
||||
|
||||
|
||||
# save the newly discovered plugins as options and default values
|
||||
conf.LOADED_PLUGINS = ccd('LOADED_PLUGINS', loaded_plugins_prefixes , c_d, 'Loaded plugins', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', str(sorted(all_plugins_prefixes)), 'General')
|
||||
|
||||
@@ -296,7 +296,54 @@ def importConfigs (db, all_plugins):
|
||||
conf.plugins_once_run = False
|
||||
# -----------------
|
||||
# Plugins END
|
||||
|
||||
# TODO check app_conf_override.json
|
||||
# Assuming fullConfFolder is defined elsewhere
|
||||
app_conf_override_path = fullConfFolder + '/app_conf_override.json'
|
||||
|
||||
if os.path.exists(app_conf_override_path):
|
||||
with open(app_conf_override_path, 'r') as f:
|
||||
try:
|
||||
# Load settings_override from the JSON file
|
||||
settings_override = json.load(f)
|
||||
|
||||
# Loop through settings_override dictionary
|
||||
for setting_name, value in settings_override.items():
|
||||
# Ensure the value is treated as a string and passed directly
|
||||
if isinstance(value, str):
|
||||
# Log the value being passed
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
mylog('debug', [f"[Config] Setting override {setting_name} with value: {value}"])
|
||||
ccd(setting_name, value, c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True)
|
||||
else:
|
||||
# Convert to string and log
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
mylog('debug', [f"[Config] Setting override {setting_name} with value: {str(value)}"])
|
||||
ccd(setting_name, str(value), c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True)
|
||||
|
||||
except json.JSONDecodeError:
|
||||
mylog('none', [f"[Config] [ERROR] Setting override decoding JSON from {app_conf_override_path}"])
|
||||
else:
|
||||
mylog('debug', [f"[Config] File {app_conf_override_path} does not exist."])
|
||||
|
||||
# Check if app was upgraded
|
||||
with open(applicationPath + '/front/buildtimestamp.txt', 'r') as f:
|
||||
|
||||
buildTimestamp = int(f.read().strip())
|
||||
cur_version = conf.VERSION
|
||||
|
||||
mylog('debug', [f"[Config] buildTimestamp: '{buildTimestamp}'"])
|
||||
mylog('debug', [f"[Config] conf.VERSION : '{cur_version}'"])
|
||||
|
||||
if str(cur_version) != str(buildTimestamp):
|
||||
|
||||
mylog('none', ['[Config] App upgraded 🚀'])
|
||||
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
ccd('VERSION', buildTimestamp , c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True)
|
||||
|
||||
write_notification(f'[Upgrade] : App upgraded 🚀 Please clear the cache: <ol> <li>Clear the browser cache (shift + browser refresh button)</li> <li> Clear app cache with the 🔄 (reload) button in the header</li></ol> Check out new features and what has changed in the <a href="https://github.com/jokob-sk/NetAlertX/releases" target="_blank">📓 release notes</a>.', 'interrupt', timeNowTZ())
|
||||
|
||||
|
||||
# Insert settings into the DB
|
||||
sql.execute ("DELETE FROM Settings")
|
||||
|
||||
Reference in New Issue
Block a user