mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Compare commits
35 Commits
79d67d1cbe
...
v25.5.24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84d8363383 | ||
|
|
3830b00c33 | ||
|
|
84103bb8ed | ||
|
|
0d7202f7a2 | ||
|
|
a1f4f9b92f | ||
|
|
82410814de | ||
|
|
98cf0a4bc0 | ||
|
|
5efc9dcb16 | ||
|
|
cfa7fb47e4 | ||
|
|
29d677253e | ||
|
|
210a5e9ae2 | ||
|
|
49465715a6 | ||
|
|
a0a14f24cc | ||
|
|
209d06421c | ||
|
|
cac2af8422 | ||
|
|
57a9b269a0 | ||
|
|
17b11a016c | ||
|
|
d05de62cc7 | ||
|
|
3c28f9ed36 | ||
|
|
56bd1d2772 | ||
|
|
7e65b06ff2 | ||
|
|
78cb68d2c4 | ||
|
|
f8df8dc41a | ||
|
|
4199f8891c | ||
|
|
7aa5f499b9 | ||
|
|
990f490fb3 | ||
|
|
7dba186e39 | ||
|
|
7443c52021 | ||
|
|
03822ac8fa | ||
|
|
01f7a18dce | ||
|
|
a392803478 | ||
|
|
c9ef1b1bce | ||
|
|
87eda72a62 | ||
|
|
984bc58cf2 | ||
|
|
4d7a55e4f6 |
79
docs/DOCKER_SWARM.md
Executable file
79
docs/DOCKER_SWARM.md
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
# Docker Swarm Deployment Guide (IPvlan)
|
||||||
|
|
||||||
|
This guide describes how to deploy **NetAlertX** in a **Docker Swarm** environment using an `ipvlan` network. This enables the container to receive a LAN IP address directly, which is ideal for network monitoring.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Step 1: Create an IPvlan Config-Only Network on All Nodes
|
||||||
|
|
||||||
|
> Run this command on **each node** in the Swarm.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network create -d ipvlan \
|
||||||
|
--subnet=192.168.1.0/24 \ # 🔧 Replace with your LAN subnet
|
||||||
|
--gateway=192.168.1.1 \ # 🔧 Replace with your LAN gateway
|
||||||
|
-o ipvlan_mode=l2 \
|
||||||
|
-o parent=eno1 \ # 🔧 Replace with your network interface (e.g., eth0, eno1)
|
||||||
|
--config-only \
|
||||||
|
ipvlan-swarm-config
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🖥️ Step 2: Create the Swarm-Scoped IPvlan Network (One-Time Setup)
|
||||||
|
|
||||||
|
> Run this on **one Swarm manager node only**.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker network create -d ipvlan \
|
||||||
|
--scope swarm \
|
||||||
|
--config-from ipvlan-swarm-config \
|
||||||
|
swarm-ipvlan
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧾 Step 3: Deploy NetAlertX with Docker Compose
|
||||||
|
|
||||||
|
Use the following Compose snippet to deploy NetAlertX with a **static LAN IP** assigned via the `swarm-ipvlan` network.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
netalertx:
|
||||||
|
image: ghcr.io/jokob-sk/netalertx:latest
|
||||||
|
ports:
|
||||||
|
- 20211:20211
|
||||||
|
volumes:
|
||||||
|
- /mnt/YOUR_SERVER/netalertx/config:/app/config:rw
|
||||||
|
- /mnt/YOUR_SERVER/netalertx/db:/netalertx/app/db:rw
|
||||||
|
- /mnt/YOUR_SERVER/netalertx/logs:/netalertx/app/log:rw
|
||||||
|
environment:
|
||||||
|
- TZ=Europe/London
|
||||||
|
- PORT=20211
|
||||||
|
networks:
|
||||||
|
swarm-ipvlan:
|
||||||
|
ipv4_address: 192.168.1.240 # ⚠️ Choose a free IP from your LAN
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.role == manager # 🔄 Or use: node.labels.netalertx == true
|
||||||
|
|
||||||
|
networks:
|
||||||
|
swarm-ipvlan:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Notes
|
||||||
|
|
||||||
|
* The `ipvlan` setup allows **NetAlertX** to have a direct IP on your LAN.
|
||||||
|
* Replace `eno1` with your interface, IP addresses, and volume paths to match your environment.
|
||||||
|
* Make sure the assigned IP (`192.168.1.240` above) is not in use or managed by DHCP.
|
||||||
|
* You may also use a node label constraint instead of `node.role == manager` for more control.
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Overview
|
# Home Assistant integration overview
|
||||||
|
|
||||||
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
|
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Welcome to the official NetAlertX documentation! NetAlertX is a powerful tool designed to simplify the management and monitoring of your network. Below, you will find guides and resources to help you set up, configure, and troubleshoot your NetAlertX instance.
|
Welcome to the official NetAlertX documentation! NetAlertX is a powerful tool designed to simplify the management and monitoring of your network. Below, you will find guides and resources to help you set up, configure, and troubleshoot your NetAlertX instance.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## In-App Help
|
## In-App Help
|
||||||
|
|
||||||
NetAlertX provides contextual help within the application:
|
NetAlertX provides contextual help within the application:
|
||||||
@@ -13,6 +15,8 @@ NetAlertX provides contextual help within the application:
|
|||||||
|
|
||||||
## Installation Guides
|
## Installation Guides
|
||||||
|
|
||||||
|
The app can be installed different ways, with the best support of the docker-based deployments. This includes the Home Assistant and Unraid installation approaches. See details below.
|
||||||
|
|
||||||
### Docker (Fully Supported)
|
### Docker (Fully Supported)
|
||||||
|
|
||||||
NetAlertX is fully supported in Docker environments, allowing for easy setup and configuration. Follow the official guide to get started:
|
NetAlertX is fully supported in Docker environments, allowing for easy setup and configuration. Follow the official guide to get started:
|
||||||
@@ -21,12 +25,25 @@ NetAlertX is fully supported in Docker environments, allowing for easy setup and
|
|||||||
|
|
||||||
This guide will take you through the process of setting up NetAlertX using Docker Compose or standalone Docker commands.
|
This guide will take you through the process of setting up NetAlertX using Docker Compose or standalone Docker commands.
|
||||||
|
|
||||||
|
### Home Assistant (Fully Supported)
|
||||||
|
|
||||||
|
You can install NetAlertX also as a Home Assistant addon [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/) repository. This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT.
|
||||||
|
|
||||||
|
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
|
||||||
|
|
||||||
|
### Unraid (Partial Support)
|
||||||
|
|
||||||
|
The Unraid template was created by the community, so it's only partially supported. Alternatively, here is [another version of the Unraid template](https://github.com/jokob-sk/NetAlertX-unraid).
|
||||||
|
|
||||||
|
- [[Installation] Unraid App](https://unraid.net/community/apps)
|
||||||
|
|
||||||
### Bare-Metal Installation (Experimental)
|
### Bare-Metal Installation (Experimental)
|
||||||
|
|
||||||
If you prefer to run NetAlertX on your own hardware, you can try the experimental bare-metal installation. Please note that this method is still under development, and we're looking for maintainers to help improve it.
|
If you prefer to run NetAlertX on your own hardware, you can try the experimental bare-metal installation. Please note that this method is still under development, and are looking for maintainers to help improve it.
|
||||||
|
|
||||||
- [Bare-Metal Installation Guide](./HW_INSTALL.md)
|
- [Bare-Metal Installation Guide](./HW_INSTALL.md)
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Help and Support
|
## Help and Support
|
||||||
@@ -66,14 +83,10 @@ To keep up with the latest changes and updates to NetAlertX, please refer to the
|
|||||||
Make sure to follow the project on GitHub to get notifications for new releases and important updates.
|
Make sure to follow the project on GitHub to get notifications for new releases and important updates.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
## Additional info
|
||||||
|
|
||||||
## Additional Resources
|
|
||||||
|
|
||||||
- **Configuration Tips**: Learn how to optimize NetAlertX for your network setup.
|
|
||||||
- **Advanced Features**: Explore advanced functionalities like plugin development and custom configurations.
|
|
||||||
- **Documentation Index**: Check out the full [documentation index](https://github.com/jokob-sk/NetAlertX/tree/main/docs) for all the guides available.
|
- **Documentation Index**: Check out the full [documentation index](https://github.com/jokob-sk/NetAlertX/tree/main/docs) for all the guides available.
|
||||||
|
|
||||||
We hope you find this documentation helpful. If you have any suggestions or improvements, please don’t hesitate to contribute!
|
If you have any suggestions or improvements, please don’t hesitate to contribute!
|
||||||
|
|
||||||
---
|
|
||||||
NetAlertX is actively maintained. You can find the source code, report bugs, or request new features on our [GitHub page](https://github.com/jokob-sk/NetAlertX).
|
NetAlertX is actively maintained. You can find the source code, report bugs, or request new features on our [GitHub page](https://github.com/jokob-sk/NetAlertX).
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
// Additional form elements like the random MAC address button for devMac
|
// Additional form elements like the random MAC address button for devMac
|
||||||
let inlineControl = "";
|
let inlineControl = "";
|
||||||
// handle rendom mac
|
// handle random mac
|
||||||
if (setting.setKey == "NEWDEV_devMac" && deviceData["devIsRandomMAC"] == true) {
|
if (setting.setKey == "NEWDEV_devMac" && deviceData["devIsRandomMAC"] == true) {
|
||||||
inlineControl += `<span class="input-group-addon pointer"
|
inlineControl += `<span class="input-group-addon pointer"
|
||||||
title="${getString("RandomMAC_hover")}">
|
title="${getString("RandomMAC_hover")}">
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ function initializeSessionsDatatable () {
|
|||||||
// Replace HTML codes
|
// Replace HTML codes
|
||||||
{targets: [0],
|
{targets: [0],
|
||||||
'createdCell': function (td, cellData, rowData, row, col) {
|
'createdCell': function (td, cellData, rowData, row, col) {
|
||||||
$(td).html (translateHTMLcodes (cellData));
|
$(td).html (translateHTMLcodes (localizeTimestamp(cellData)));
|
||||||
} }
|
} }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -219,9 +219,8 @@ function initializeCalendar() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
eventRender: function (event, element) {
|
eventRender: function (event, element) {
|
||||||
$(element).tooltip({container: 'body', placement: 'bottom',
|
// $(element).tooltip({container: 'body', placement: 'bottom', title: event.tooltip});
|
||||||
title: event.tooltip});
|
element.attr ('title', event.tooltip); // Alternative tooltip
|
||||||
// element.attr ('title', event.tooltip); // Alternative tooltip
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loading: function( isLoading, view ) {
|
loading: function( isLoading, view ) {
|
||||||
|
|||||||
@@ -47,9 +47,28 @@
|
|||||||
{visible: false, targets: [0]},
|
{visible: false, targets: [0]},
|
||||||
|
|
||||||
// Replace HTML codes
|
// Replace HTML codes
|
||||||
{targets: [1,2,3,5],
|
{targets: [3,5],
|
||||||
'createdCell': function (td, cellData, rowData, row, col) {
|
'createdCell': function (td, cellData, rowData, row, col) {
|
||||||
$(td).html (translateHTMLcodes (cellData));
|
$(td).html (translateHTMLcodes (cellData));
|
||||||
|
} },
|
||||||
|
// Date
|
||||||
|
{targets: [1,2],
|
||||||
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
|
// console.log(cellData);
|
||||||
|
|
||||||
|
if (!cellData.includes("missing event") && !cellData.includes("..."))
|
||||||
|
{
|
||||||
|
if (cellData.includes("+")) { // Check if timezone offset is present
|
||||||
|
cellData = cellData.split('+')[0]; // Remove timezone offset
|
||||||
|
}
|
||||||
|
// console.log(cellData);
|
||||||
|
result = localizeTimestamp(cellData);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
result = translateHTMLcodes(cellData)
|
||||||
|
}
|
||||||
|
|
||||||
|
$(td).html (result);
|
||||||
} }
|
} }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ function initializeDatatable () {
|
|||||||
} },
|
} },
|
||||||
|
|
||||||
// Replace HTML codes
|
// Replace HTML codes
|
||||||
{targets: [3,4,5,6,7],
|
{targets: [4,5,6,7],
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
$(td).html (translateHTMLcodes (cellData));
|
$(td).html (translateHTMLcodes (cellData));
|
||||||
} },
|
} },
|
||||||
@@ -226,6 +226,12 @@ function initializeDatatable () {
|
|||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
// console.log(cellData);
|
// console.log(cellData);
|
||||||
$(td).html (cellData);
|
$(td).html (cellData);
|
||||||
|
} },
|
||||||
|
// Date
|
||||||
|
{targets: [3],
|
||||||
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
|
// console.log(cellData);
|
||||||
|
$(td).html (localizeTimestamp(cellData));
|
||||||
} }
|
} }
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -353,6 +353,28 @@ function getLangCode() {
|
|||||||
// String utilities
|
// String utilities
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
function localizeTimestamp(result)
|
||||||
|
{
|
||||||
|
|
||||||
|
// contains TZ in format Europe/Berlin
|
||||||
|
tz = getSetting("TIMEZONE")
|
||||||
|
|
||||||
|
const date = new Date(result); // Assumes result is a timestamp or ISO string
|
||||||
|
const formatter = new Intl.DateTimeFormat('default', {
|
||||||
|
timeZone: tz,
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
hour12: false // change to true if you want AM/PM format
|
||||||
|
});
|
||||||
|
|
||||||
|
return formatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Replaces double quotes within single-quoted strings, then converts all single quotes to double quotes,
|
* Replaces double quotes within single-quoted strings, then converts all single quotes to double quotes,
|
||||||
|
|||||||
5
front/lib/popper_tooltip/popper.min.js
vendored
Executable file
5
front/lib/popper_tooltip/popper.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
@@ -42,6 +42,7 @@
|
|||||||
<script src="lib/datatables.net/js/jquery.dataTables.min.js"></script>
|
<script src="lib/datatables.net/js/jquery.dataTables.min.js"></script>
|
||||||
<script src="lib/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
|
<script src="lib/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="lib/datatables.net/js/dataTables.select.min.js"></script>
|
<script src="lib/datatables.net/js/dataTables.select.min.js"></script>
|
||||||
|
<script src="lib/popper_tooltip/popper.min.js"></script>
|
||||||
|
|
||||||
<script src="js/common.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
<script src="js/common.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||||
<script src="js/modal.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
<script src="js/modal.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||||
@@ -120,34 +121,8 @@
|
|||||||
let timeZone = "<?php echo $timeZone ?>";
|
let timeZone = "<?php echo $timeZone ?>";
|
||||||
let now = new Date();
|
let now = new Date();
|
||||||
|
|
||||||
// Convert to the specified time zone
|
|
||||||
let formatter = new Intl.DateTimeFormat("en-UK", {
|
|
||||||
timeZone: timeZone,
|
|
||||||
day: "2-digit",
|
|
||||||
month: "short",
|
|
||||||
year: "numeric",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
second: "2-digit",
|
|
||||||
hour12: false, // Use 24-hour format
|
|
||||||
});
|
|
||||||
let parts = formatter.formatToParts(now);
|
|
||||||
|
|
||||||
// Extract date components
|
|
||||||
let day = parts.find(p => p.type === "day").value;
|
|
||||||
let month = parts.find(p => p.type === "month").value;
|
|
||||||
let year = parts.find(p => p.type === "year").value;
|
|
||||||
|
|
||||||
// Extract time components
|
|
||||||
let hour = parts.find(p => p.type === "hour").value;
|
|
||||||
let minute = parts.find(p => p.type === "minute").value;
|
|
||||||
let second = parts.find(p => p.type === "second").value;
|
|
||||||
|
|
||||||
// Construct the date and time in DD-MMM-YYYY HH:MM:SS format
|
|
||||||
let formattedDateTime = `${day}-${month}-${year} ${hour}:${minute}:${second}`;
|
|
||||||
|
|
||||||
if (document.getElementById) {
|
if (document.getElementById) {
|
||||||
document.getElementById("NAX_Servertime_plc").innerHTML = '(' + formattedDateTime + ')';
|
document.getElementById("NAX_Servertime_plc").innerHTML = '(' + localizeTimestamp(now) + ')';
|
||||||
document.getElementById("NAX_TZ").innerHTML = timeZone;
|
document.getElementById("NAX_TZ").innerHTML = timeZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
"About_Design": "",
|
"About_Design": "",
|
||||||
"About_Exit": "",
|
"About_Exit": "",
|
||||||
"About_Title": "",
|
"About_Title": "",
|
||||||
"AppEvents_AppEventProcessed": "",
|
"AppEvents_AppEventProcessed": "Zpracováno",
|
||||||
"AppEvents_DateTimeCreated": "",
|
"AppEvents_DateTimeCreated": "Zalogováno",
|
||||||
"AppEvents_Extra": "Extra",
|
"AppEvents_Extra": "Extra",
|
||||||
"AppEvents_GUID": "",
|
"AppEvents_GUID": "",
|
||||||
"AppEvents_Helper1": "",
|
"AppEvents_Helper1": "",
|
||||||
|
|||||||
18
front/php/templates/language/de_de.json
Executable file → Normal file
18
front/php/templates/language/de_de.json
Executable file → Normal file
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"API_CUSTOM_SQL_description": "Benutzerdefinierte SQL-Abfrage, welche eine JSON-Datei generiert und diese mit dem <a href=\"/php/server/query_json.php?file=table_custom_endpoint.json\" target=\"_blank\">Dateiendpunkt <code>table_custom_endpoint.json</code></a> zur Verfügung stellt.",
|
"API_CUSTOM_SQL_description": "Benutzerdefinierte SQL-Abfrage, welche eine JSON-Datei generiert und diese mit dem <a href=\"/php/server/query_json.php?file=table_custom_endpoint.json\" target=\"_blank\">Dateiendpunkt <code>table_custom_endpoint.json</code></a> zur Verfügung stellt.",
|
||||||
"API_CUSTOM_SQL_name": "Benutzerdefinierte SQL-Abfrage",
|
"API_CUSTOM_SQL_name": "Benutzerdefinierte SQL-Abfrage",
|
||||||
"API_TOKEN_description": "API-Token zur Absicherung der Kommunikation – Sie können einen generieren oder einen beliebigen Wert eingeben. Er wird im Anfrage-Header übermittelt. Wird im <code>SYNC</code>-Plugin und GraphQL-Server verwendet.",
|
"API_TOKEN_description": "API-Token zur Absicherung der Kommunikation – Sie können einen neuen generieren oder einen beliebigen Wert eingeben. Er wird im Anfrage-Header übermittelt und zum Beispiel im <code>SYNC</code>-Plugin, im GraphQL-Server und in anderen API Endpunkten verwendet (siehe auch <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md\" target=\"_blank\">API Dokumentation)</a>..",
|
||||||
"API_TOKEN_name": "API-Schlüssel",
|
"API_TOKEN_name": "API-Schlüssel",
|
||||||
"API_display_name": "API",
|
"API_display_name": "API",
|
||||||
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
"BackDevices_DBTools_ImportCSVError": "Die CSV-Datei konnte nicht importiert werden. Stellen Sie sicher, dass das Format korrekt ist.",
|
"BackDevices_DBTools_ImportCSVError": "Die CSV-Datei konnte nicht importiert werden. Stellen Sie sicher, dass das Format korrekt ist.",
|
||||||
"BackDevices_DBTools_ImportCSVMissing": "Die CSV-Datei konnte nicht in <b>/config/devices.csv</b> gefunden werden.",
|
"BackDevices_DBTools_ImportCSVMissing": "Die CSV-Datei konnte nicht in <b>/config/devices.csv</b> gefunden werden.",
|
||||||
"BackDevices_DBTools_Purge": "Die ältesten Backups wurden gelöscht",
|
"BackDevices_DBTools_Purge": "Die ältesten Backups wurden gelöscht",
|
||||||
"BackDevices_DBTools_UpdDev": "Gerät wurde erfolgreich aktualisiert",
|
"BackDevices_DBTools_UpdDev": "Gerät wurde erfolgreich aktualisiert. Es kann etwas dauern bis die Übersicht neu geladen ist, wenn ein Scan aktiv ist.",
|
||||||
"BackDevices_DBTools_UpdDevError": "Fehler beim Aktualisieren des Gerätes",
|
"BackDevices_DBTools_UpdDevError": "Fehler beim Aktualisieren des Gerätes",
|
||||||
"BackDevices_DBTools_Upgrade": "Datenbank wurde erfolgreich aktualisiert",
|
"BackDevices_DBTools_Upgrade": "Datenbank wurde erfolgreich aktualisiert",
|
||||||
"BackDevices_DBTools_UpgradeError": "Fehler beim Aktualisieren der Datenbank",
|
"BackDevices_DBTools_UpgradeError": "Fehler beim Aktualisieren der Datenbank",
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
"CustProps_cant_remove": "Kann nicht entfernt werden, es wird mindestens eine Eigenschaft benötigt.",
|
"CustProps_cant_remove": "Kann nicht entfernt werden, es wird mindestens eine Eigenschaft benötigt.",
|
||||||
"DAYS_TO_KEEP_EVENTS_description": "Dies ist eine Wartungseinstellung. Spezifiziert wie viele Tage Events gespeichert bleiben. Alle älteren Events werden periodisch gelöscht. Wird auch auf die Plugins History angewendet.",
|
"DAYS_TO_KEEP_EVENTS_description": "Dies ist eine Wartungseinstellung. Spezifiziert wie viele Tage Events gespeichert bleiben. Alle älteren Events werden periodisch gelöscht. Wird auch auf die Plugins History angewendet.",
|
||||||
"DAYS_TO_KEEP_EVENTS_name": "Ereignisse löschen, die älter sind als",
|
"DAYS_TO_KEEP_EVENTS_name": "Ereignisse löschen, die älter sind als",
|
||||||
"DISCOVER_PLUGINS_description": "Deaktiviere diese Option um die Initialisierung und Speicherdauer der Einstellungen zu verringern. Wenn es deaktiviert ist, können keine Plugins gefunden oder neue Plugins zu den vorhandenen hinzugefügt werden.",
|
"DISCOVER_PLUGINS_description": "Deaktiviere diese Option, um Initialisierung und Speichern der Einstellungen zu beschleunigen. Wenn es deaktiviert ist, werden keine neuen Plugins gefunden und es können keine manuell hinzugefügt werden.",
|
||||||
"DISCOVER_PLUGINS_name": "Entdecke Erweiterungen",
|
"DISCOVER_PLUGINS_name": "Entdecke Erweiterungen",
|
||||||
"DevDetail_Copy_Device_Title": "Details von Gerät kopieren",
|
"DevDetail_Copy_Device_Title": "Details von Gerät kopieren",
|
||||||
"DevDetail_Copy_Device_Tooltip": "Details vom Gerät aus der Dropdown-Liste kopieren. Alles auf dieser Seite wird überschrieben",
|
"DevDetail_Copy_Device_Tooltip": "Details vom Gerät aus der Dropdown-Liste kopieren. Alles auf dieser Seite wird überschrieben",
|
||||||
@@ -295,7 +295,7 @@
|
|||||||
"Events_Tablelenght": "Zeige _MENU_ Einträge",
|
"Events_Tablelenght": "Zeige _MENU_ Einträge",
|
||||||
"Events_Tablelenght_all": "Alle",
|
"Events_Tablelenght_all": "Alle",
|
||||||
"Events_Title": "Ereignisse",
|
"Events_Title": "Ereignisse",
|
||||||
"GRAPHQL_PORT_description": "Die Portnummer des GraphQL-Servers.",
|
"GRAPHQL_PORT_description": "Die Portnummer des GraphQL-Servers. Stellen Sie sicher, dass dieser Port von keiner anderen Anwendung oder NetAlertX Instanz verwendet wird.",
|
||||||
"GRAPHQL_PORT_name": "GraphQL-Port",
|
"GRAPHQL_PORT_name": "GraphQL-Port",
|
||||||
"Gen_Action": "Action",
|
"Gen_Action": "Action",
|
||||||
"Gen_Add": "Hinzufügen",
|
"Gen_Add": "Hinzufügen",
|
||||||
@@ -341,7 +341,7 @@
|
|||||||
"Gen_Warning": "Warnung",
|
"Gen_Warning": "Warnung",
|
||||||
"Gen_Work_In_Progress": "Keine Finalversion, feedback bitte unter: https://github.com/jokob-sk/NetAlertX/issues",
|
"Gen_Work_In_Progress": "Keine Finalversion, feedback bitte unter: https://github.com/jokob-sk/NetAlertX/issues",
|
||||||
"Gen_create_new_device": "Neues Gerät",
|
"Gen_create_new_device": "Neues Gerät",
|
||||||
"Gen_create_new_device_info": "",
|
"Gen_create_new_device_info": "Geräte werden normalerweise über <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">Plugins</a> gefunden. In Ausnahmefällen kann es nötig sein, sie manuell hinzuzufügen. Konkrete Szenarien sind in der <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md\">Dokumentation über entfernte Netzwerke</a> zu finden.",
|
||||||
"General_display_name": "Allgemein",
|
"General_display_name": "Allgemein",
|
||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung <b>DELETING devices</b>. Wenn aktiviert (<code>0</code> bedeutet deaktiviert), werden als <b>\"Neues Gerät\"</b> markierte Geräte gelöscht, wenn ihre <b>erste Sitzung</b> länger her ist als in dieser Einstellung angegeben. Verwenden Sie diese Einstellung, wenn Sie <b>Neue Geräte</b> nach <code>X</code> Stunden automatisch löschen wollen.",
|
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung <b>DELETING devices</b>. Wenn aktiviert (<code>0</code> bedeutet deaktiviert), werden als <b>\"Neues Gerät\"</b> markierte Geräte gelöscht, wenn ihre <b>erste Sitzung</b> länger her ist als in dieser Einstellung angegeben. Verwenden Sie diese Einstellung, wenn Sie <b>Neue Geräte</b> nach <code>X</code> Stunden automatisch löschen wollen.",
|
||||||
@@ -383,11 +383,11 @@
|
|||||||
"MQTT_icon": "<i class=\"fa fa-square-rss\"></i>",
|
"MQTT_icon": "<i class=\"fa fa-square-rss\"></i>",
|
||||||
"Maint_PurgeLog": "Protokoll bereinigen",
|
"Maint_PurgeLog": "Protokoll bereinigen",
|
||||||
"Maint_RestartServer": "Server neu starten",
|
"Maint_RestartServer": "Server neu starten",
|
||||||
"Maint_Restart_Server_noti_text": "",
|
"Maint_Restart_Server_noti_text": "Soll der Backend-Server wirklich neu gestartet werden? Das könnte Instabilitäten verursachen. Vorher ein Backup erstellen. <br/><br/>Hinweis: Das kann einige Minuten dauern.",
|
||||||
"Maintenance_Running_Version": "Installierte Version",
|
"Maintenance_Running_Version": "Installierte Version",
|
||||||
"Maintenance_Status": "Status",
|
"Maintenance_Status": "Status",
|
||||||
"Maintenance_Title": "Wartungswerkzeuge",
|
"Maintenance_Title": "Wartungswerkzeuge",
|
||||||
"Maintenance_Tool_DownloadConfig": "",
|
"Maintenance_Tool_DownloadConfig": "Einstellungen exportieren",
|
||||||
"Maintenance_Tool_DownloadConfig_text": "",
|
"Maintenance_Tool_DownloadConfig_text": "",
|
||||||
"Maintenance_Tool_DownloadWorkflows": "",
|
"Maintenance_Tool_DownloadWorkflows": "",
|
||||||
"Maintenance_Tool_DownloadWorkflows_text": "",
|
"Maintenance_Tool_DownloadWorkflows_text": "",
|
||||||
@@ -479,7 +479,7 @@
|
|||||||
"Maintenance_lang_selector_apply": "Übernehmen",
|
"Maintenance_lang_selector_apply": "Übernehmen",
|
||||||
"Maintenance_lang_selector_empty": "Sprache wählen",
|
"Maintenance_lang_selector_empty": "Sprache wählen",
|
||||||
"Maintenance_lang_selector_lable": "Sprachauswahl",
|
"Maintenance_lang_selector_lable": "Sprachauswahl",
|
||||||
"Maintenance_lang_selector_text": "Die Änderung findet serverseitig statt, betrifft also alle verwendeten Geräte.",
|
"Maintenance_lang_selector_text": "Die Änderung findet clientseitig statt, betrifft also nur den aktuellen Browser.",
|
||||||
"Maintenance_new_version": "Eine neue Version ist vefügbar. Sieh dir die <a href=\"https://github.com/jokob-sk/NetAlertX/releases\" target=\"_blank\">Versionshinweise</a> an.",
|
"Maintenance_new_version": "Eine neue Version ist vefügbar. Sieh dir die <a href=\"https://github.com/jokob-sk/NetAlertX/releases\" target=\"_blank\">Versionshinweise</a> an.",
|
||||||
"Maintenance_themeselector_apply": "Übernehmen",
|
"Maintenance_themeselector_apply": "Übernehmen",
|
||||||
"Maintenance_themeselector_empty": "Skin wählen",
|
"Maintenance_themeselector_empty": "Skin wählen",
|
||||||
@@ -823,4 +823,4 @@
|
|||||||
"settings_update_item_warning": "",
|
"settings_update_item_warning": "",
|
||||||
"test_event_icon": "",
|
"test_event_icon": "",
|
||||||
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
|
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices marked as <b>New Device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New Devices</b> after <code>X</code> hours.",
|
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices marked as <b>New Device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New Devices</b> after <code>X</code> hours.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name": "Delete new devices after",
|
"HRS_TO_KEEP_NEWDEV_name": "Delete new devices after",
|
||||||
"HRS_TO_KEEP_OFFDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices that are <b>Offline</b> and their <b>Last Offline</b> date time is older than the specified hours in this setting, will be deleted. Use this setting if you want to auto-delete <b>Offline Devices</b> after <code>X</code> hours being offline.",
|
"HRS_TO_KEEP_OFFDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices that are <b>Offline</b> and their <b>Last Connection</b> date time is older than the specified hours in this setting, will be deleted. Use this setting if you want to auto-delete <b>Offline Devices</b> after <code>X</code> hours being offline.",
|
||||||
"HRS_TO_KEEP_OFFDEV_name": "Delete offline devices after",
|
"HRS_TO_KEEP_OFFDEV_name": "Delete offline devices after",
|
||||||
"LOADED_PLUGINS_description": "Which Plugins to load. Adding plugins might slow the application. Read more about which plugins need to be enabled, types, or scanning options in the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins docs</a>. Unloaded plugins will lose your settings. Only <code>disabled</code> plugins can be unloaded.",
|
"LOADED_PLUGINS_description": "Which Plugins to load. Adding plugins might slow the application. Read more about which plugins need to be enabled, types, or scanning options in the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins docs</a>. Unloaded plugins will lose your settings. Only <code>disabled</code> plugins can be unloaded.",
|
||||||
"LOADED_PLUGINS_name": "Loaded plugins",
|
"LOADED_PLUGINS_name": "Loaded plugins",
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "Paramètre de maintenance. S'il est activé (<code>0</code> s'il est désactivé), les appareils marqués comme <b>Nouvel appareil</b> seront supprimés si leur durée depuis la <b>première session</b> est plus ancienne que le nombre d'heures paramétré. Utilisez ce paramétrage si vous voulez supprimer automatiquement les <b>Nouveaux appareils</b> après <code>X</code> heures.",
|
"HRS_TO_KEEP_NEWDEV_description": "Paramètre de maintenance. S'il est activé (<code>0</code> s'il est désactivé), les appareils marqués comme <b>Nouvel appareil</b> seront supprimés si leur durée depuis la <b>première session</b> est plus ancienne que le nombre d'heures paramétré. Utilisez ce paramétrage si vous voulez supprimer automatiquement les <b>Nouveaux appareils</b> après <code>X</code> heures.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name": "Supprimer les nouveaux appareils après",
|
"HRS_TO_KEEP_NEWDEV_name": "Supprimer les nouveaux appareils après",
|
||||||
"HRS_TO_KEEP_OFFDEV_description": "Il s'agit d'un paramètre de maintenance <b>SUPPRIMER des appareils</b>. Si cette option est activée (<code>0</code> est désactivé), les appareils qui sont <b>Hors ligne</b> et dont la <b>dernière heure hors ligne</b> est plus ancienne que les heures spécifiées dans ce paramètre. Utilisez ce paramètre si vous souhaitez supprimer automatiquement <b>Appareils hors ligne</b> après <code>X</code> heures de déconnexion.",
|
"HRS_TO_KEEP_OFFDEV_description": "Il s'agit d'un paramètre de maintenance <b>SUPPRIMER des appareils</b>. Si cette option est activée (<code>0</code> est désactivé), les appareils qui sont <b>Hors ligne</b> et dont la <b>dernière connexion</b> est plus ancienne que les heures spécifiées dans ce paramètre. Utilisez ce paramètre si vous souhaitez supprimer automatiquement <b>Appareils hors ligne</b> après <code>X</code> heures de déconnexion.",
|
||||||
"HRS_TO_KEEP_OFFDEV_name": "Supprimez les appareils hors ligne après",
|
"HRS_TO_KEEP_OFFDEV_name": "Supprimez les appareils hors ligne après",
|
||||||
"LOADED_PLUGINS_description": "Affiche les plugins chargés. Ajouter des plugins peut ralentir l'application. Obtenez plus d'informations dur quels plugins dont à activer, ou les options de scan dans la <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">documentation des plugins</a>. Décharger des plugins leur fait perdre leurs paramètres. Seuls les plugins <code>désactivés</code> peuvent être déchargés.",
|
"LOADED_PLUGINS_description": "Affiche les plugins chargés. Ajouter des plugins peut ralentir l'application. Obtenez plus d'informations dur quels plugins dont à activer, ou les options de scan dans la <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">documentation des plugins</a>. Décharger des plugins leur fait perdre leurs paramètres. Seuls les plugins <code>désactivés</code> peuvent être déchargés.",
|
||||||
"LOADED_PLUGINS_name": "Plugins chargés",
|
"LOADED_PLUGINS_name": "Plugins chargés",
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), tutti i dispositivi marcati con <b>Nuovo dispositivo</b> verranno eliminati se l'orario della <b>Prima sessione</b> è precedente all'orario di questa impostazione. Usa questa impostazione se vuoi eliminare automaticamente i <b>Nuovi dispositivi</b> dopo <code>X</code> ore.",
|
"HRS_TO_KEEP_NEWDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), tutti i dispositivi marcati con <b>Nuovo dispositivo</b> verranno eliminati se l'orario della <b>Prima sessione</b> è precedente all'orario di questa impostazione. Usa questa impostazione se vuoi eliminare automaticamente i <b>Nuovi dispositivi</b> dopo <code>X</code> ore.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name": "Elimina nuovi dispositivi dopo",
|
"HRS_TO_KEEP_NEWDEV_name": "Elimina nuovi dispositivi dopo",
|
||||||
"HRS_TO_KEEP_OFFDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), i dispositivi che sono <b>Offline</b> e la loro data e ora <b>Ultima offline</b> sono più vecchi delle ore specificate in questa impostazione saranno eliminati. Usa questa impostazione se vuoi eliminare automaticamente <b>Dispositivi offline</b> dopo <code>X</code> ore trascorse offline.",
|
"HRS_TO_KEEP_OFFDEV_description": "Questa è un'impostazione di manutenzione <b>ELIMINAZIONE dispositivi</b>. Se abilitata (<code>0</code> è disabilitata), i dispositivi che sono <b>Offline</b> e la loro data e ora <b>Ultima connessione</b> sono più vecchi delle ore specificate in questa impostazione saranno eliminati. Usa questa impostazione se vuoi eliminare automaticamente <b>Dispositivi offline</b> dopo <code>X</code> ore trascorse offline.",
|
||||||
"HRS_TO_KEEP_OFFDEV_name": "Elimina dispositivi offline dopo",
|
"HRS_TO_KEEP_OFFDEV_name": "Elimina dispositivi offline dopo",
|
||||||
"LOADED_PLUGINS_description": "Quali Plugin caricare. L'aggiunta di plugin potrebbe rallentare l'applicazione. Leggi di più su quali plugin necessitano di essere abilitati, tipi e opzioni di scansione nella <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">documentazione plugin</a>. I plugin disinstallati perdono la loro configurazione. Solo i plugin <code>disabilitati</code> possono essere disinstallati.",
|
"LOADED_PLUGINS_description": "Quali Plugin caricare. L'aggiunta di plugin potrebbe rallentare l'applicazione. Leggi di più su quali plugin necessitano di essere abilitati, tipi e opzioni di scansione nella <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">documentazione plugin</a>. I plugin disinstallati perdono la loro configurazione. Solo i plugin <code>disabilitati</code> possono essere disinstallati.",
|
||||||
"LOADED_PLUGINS_name": "Plugin caricati",
|
"LOADED_PLUGINS_name": "Plugin caricati",
|
||||||
|
|||||||
@@ -742,4 +742,4 @@
|
|||||||
"settings_update_item_warning": "",
|
"settings_update_item_warning": "",
|
||||||
"test_event_icon": "",
|
"test_event_icon": "",
|
||||||
"test_event_tooltip": "Guarde as alterações antes de testar as definições."
|
"test_event_tooltip": "Guarde as alterações antes de testar as definições."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "Это настройка обслуживания <b>УДАЛЕНИЕ устройств</b>. Если этот параметр включен (<code>0</code> отключен), устройства, помеченные как <b>Новое устройство</b>, будут удалены, если время их <b>Первого сеанса</b> было старше указанных в этой настройке часов. Используйте этот параметр, если вы хотите автоматически удалять <b>Новые устройства</b> через <code>X</code> часов.",
|
"HRS_TO_KEEP_NEWDEV_description": "Это настройка обслуживания <b>УДАЛЕНИЕ устройств</b>. Если этот параметр включен (<code>0</code> отключен), устройства, помеченные как <b>Новое устройство</b>, будут удалены, если время их <b>Первого сеанса</b> было старше указанных в этой настройке часов. Используйте этот параметр, если вы хотите автоматически удалять <b>Новые устройства</b> через <code>X</code> часов.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name": "Удалить новые устройства после",
|
"HRS_TO_KEEP_NEWDEV_name": "Удалить новые устройства после",
|
||||||
"HRS_TO_KEEP_OFFDEV_description": "Это настройка обслуживания <b>УДАЛЕНИЕ устройств</b>. Если этот параметр включен (<code>0</code> отключен), устройства, которые находятся <b>в Offline</b> и их дата и время <b>последнего Offline</b> старше, чем часы, указанные в этом параметре. Используйте этот параметр, если вы хотите автоматически удалять <b>Offline устройства</b> после <code>X</code> часов отсутствия в сети.",
|
"HRS_TO_KEEP_OFFDEV_description": "Это настройка обслуживания <b>УДАЛЕНИЕ устройств</b>. Если этот параметр включен (<code>0</code> отключен), устройства, которые находятся <b>в Offline</b> и их дата и время <b>последнего подключения</b> старше, чем часы, указанные в этом параметре. Используйте этот параметр, если вы хотите автоматически удалять <b>Offline устройства</b> после <code>X</code> часов отсутствия в сети.",
|
||||||
"HRS_TO_KEEP_OFFDEV_name": "Удалить устройства Offline после",
|
"HRS_TO_KEEP_OFFDEV_name": "Удалить устройства Offline после",
|
||||||
"LOADED_PLUGINS_description": "Какие плагины загружать. Добавление плагинов может замедлить работу приложения. Подробнее о том, какие плагины необходимо включить, их типах или параметрах сканирования, читайте в <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md \">Документация по плагинам</a>. Выгруженные плагины потеряют ваши настройки. Можно выгрузить только <code>отключенные</code> плагины.",
|
"LOADED_PLUGINS_description": "Какие плагины загружать. Добавление плагинов может замедлить работу приложения. Подробнее о том, какие плагины необходимо включить, их типах или параметрах сканирования, читайте в <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md \">Документация по плагинам</a>. Выгруженные плагины потеряют ваши настройки. Можно выгрузить только <code>отключенные</code> плагины.",
|
||||||
"LOADED_PLUGINS_name": "Загруженные плагины",
|
"LOADED_PLUGINS_name": "Загруженные плагины",
|
||||||
|
|||||||
0
front/php/templates/language/tr_tr.json
Normal file → Executable file
0
front/php/templates/language/tr_tr.json
Normal file → Executable file
@@ -334,7 +334,7 @@
|
|||||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||||
"HRS_TO_KEEP_NEWDEV_description": "Це налаштування обслуговування <b>ВИДАЛЕННЯ пристроїв</b>. Якщо ввімкнено (<code>0</code> вимкнено), пристрої, позначені як <b>Новий пристрій</b>, буде видалено, якщо час їхнього <b>першого сеансу</b> був старшим за вказані години в цьому налаштування. Використовуйте це налаштування, якщо ви хочете автоматично видаляти <b>Нові пристрої</b> через <code>X</code> годин.",
|
"HRS_TO_KEEP_NEWDEV_description": "Це налаштування обслуговування <b>ВИДАЛЕННЯ пристроїв</b>. Якщо ввімкнено (<code>0</code> вимкнено), пристрої, позначені як <b>Новий пристрій</b>, буде видалено, якщо час їхнього <b>першого сеансу</b> був старшим за вказані години в цьому налаштування. Використовуйте це налаштування, якщо ви хочете автоматично видаляти <b>Нові пристрої</b> через <code>X</code> годин.",
|
||||||
"HRS_TO_KEEP_NEWDEV_name": "Видаліть нові пристрої після",
|
"HRS_TO_KEEP_NEWDEV_name": "Видаліть нові пристрої після",
|
||||||
"HRS_TO_KEEP_OFFDEV_description": "Це налаштування обслуговування <b>ВИДАЛЕННЯ пристроїв</b>. Якщо ввімкнути (<code>0</code> вимкнено), пристрої, які <b>офлайн</b> і дата їх <b>останнього вимкнення</b> старші за вказані години в цьому параметрі, будуть бути видалено. Використовуйте це налаштування, якщо ви хочете автоматично видаляти <b>Автономні пристрої</b> після <code>X</code> годин роботи в режимі офлайн.",
|
"HRS_TO_KEEP_OFFDEV_description": "Це налаштування обслуговування <b>ВИДАЛЕННЯ пристроїв</b>. Якщо ввімкнено (<code>0</code> вимкнено), пристрої, які <b>офлайн</b>, та їх <b>Останнє підключення</b> дата та час старіші за вказані години в цьому налаштуванні, будуть видалені. Використовуйте це налаштування, якщо ви хочете автоматично видаляти <b>офлайн-пристрої</b> після <code>X</code> годин перебування в мережі.",
|
||||||
"HRS_TO_KEEP_OFFDEV_name": "Видаліть офлайн-пристрої після",
|
"HRS_TO_KEEP_OFFDEV_name": "Видаліть офлайн-пристрої після",
|
||||||
"LOADED_PLUGINS_description": "Які плагіни завантажити. Додавання плагінів може уповільнити роботу програми. Дізнайтеся більше про те, які плагіни потрібно ввімкнути, типи чи параметри сканування в <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md \">документи плагінів</a>. Вивантажені плагіни втратять налаштування. Лише <code>вимкнені</code> плагіни можна вивантажити.",
|
"LOADED_PLUGINS_description": "Які плагіни завантажити. Додавання плагінів може уповільнити роботу програми. Дізнайтеся більше про те, які плагіни потрібно ввімкнути, типи чи параметри сканування в <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md \">документи плагінів</a>. Вивантажені плагіни втратять налаштування. Лише <code>вимкнені</code> плагіни можна вивантажити.",
|
||||||
"LOADED_PLUGINS_name": "Завантажені плагіни",
|
"LOADED_PLUGINS_name": "Завантажені плагіни",
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
|
||||||
|
from messaging.in_app import write_notification
|
||||||
import conf
|
import conf
|
||||||
|
|
||||||
# Make sure the TIMEZONE for logging is correct
|
# Make sure the TIMEZONE for logging is correct
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from plugin_utils import getPluginObject
|
|||||||
from plugin_helper import Plugin_Objects
|
from plugin_helper import Plugin_Objects
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value, bytes_to_string, sanitize_string, cleanDeviceName
|
from helper import timeNowTZ, get_setting_value, bytes_to_string, sanitize_string, cleanDeviceName
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB, get_device_stats
|
from database import DB, get_device_stats
|
||||||
|
|
||||||
pluginName = 'TESTONLY'
|
pluginName = 'TESTONLY'
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from const import confFileName, logPath
|
|||||||
from plugin_helper import Plugin_Objects
|
from plugin_helper import Plugin_Objects
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -50,8 +50,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -658,7 +658,7 @@
|
|||||||
"description": [
|
"description": [
|
||||||
{
|
{
|
||||||
"language_code": "en_us",
|
"language_code": "en_us",
|
||||||
"string": "Email address to which the notification will be send to."
|
"string": "Email address to which the notification will be send to. You can enter multiple emails separated by a comma (<code>,</code>)."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"language_code": "es_es",
|
"language_code": "es_es",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from const import confFileName, logPath
|
|||||||
from plugin_helper import Plugin_Objects
|
from plugin_helper import Plugin_Objects
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value, hide_email
|
from helper import timeNowTZ, get_setting_value, hide_email
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
@@ -119,44 +119,58 @@ def send(pHTML, pText):
|
|||||||
|
|
||||||
subject, from_email, to_email, message_html, message_text = sanitize_email_content('NetAlertX Report', get_setting_value("SMTP_REPORT_FROM"), get_setting_value("SMTP_REPORT_TO"), pHTML, pText)
|
subject, from_email, to_email, message_html, message_text = sanitize_email_content('NetAlertX Report', get_setting_value("SMTP_REPORT_FROM"), get_setting_value("SMTP_REPORT_TO"), pHTML, pText)
|
||||||
|
|
||||||
# Compose email
|
emails = []
|
||||||
msg = MIMEMultipart('alternative')
|
|
||||||
msg['Subject'] = subject
|
|
||||||
msg['From'] = from_email
|
|
||||||
msg['To'] = to_email
|
|
||||||
msg['Date'] = formatdate(localtime=True)
|
|
||||||
|
|
||||||
msg.attach (MIMEText (message_text, 'plain'))
|
|
||||||
msg.attach (MIMEText (message_html, 'html'))
|
|
||||||
|
|
||||||
# Set a timeout for the SMTP connection (in seconds)
|
|
||||||
smtp_timeout = 30
|
|
||||||
|
|
||||||
mylog('debug', ['Trying to open connection to ' + str(get_setting_value('SMTP_SERVER')) + ':' + str(get_setting_value('SMTP_PORT'))])
|
|
||||||
|
|
||||||
if get_setting_value("LOG_LEVEL") == 'debug':
|
|
||||||
|
|
||||||
send_email(msg,smtp_timeout)
|
|
||||||
|
|
||||||
|
# handle multiple emails
|
||||||
|
if ',' in to_email:
|
||||||
|
emails = to_email.split(',')
|
||||||
else:
|
else:
|
||||||
|
emails.append(to_email)
|
||||||
|
|
||||||
|
mylog('debug', [f'[{pluginName}] Sending emails to {emails}'])
|
||||||
|
|
||||||
|
for mail_addr in emails:
|
||||||
|
|
||||||
|
mail_addr = mail_addr.strip()
|
||||||
|
|
||||||
|
# Compose email
|
||||||
|
msg = MIMEMultipart('alternative')
|
||||||
|
msg['Subject'] = subject
|
||||||
|
msg['From'] = from_email
|
||||||
|
msg['To'] = mail_addr
|
||||||
|
msg['Date'] = formatdate(localtime=True)
|
||||||
|
|
||||||
|
msg.attach (MIMEText (message_text, 'plain'))
|
||||||
|
msg.attach (MIMEText (message_html, 'html'))
|
||||||
|
|
||||||
|
# Set a timeout for the SMTP connection (in seconds)
|
||||||
|
smtp_timeout = 30
|
||||||
|
|
||||||
|
mylog('debug', ['Trying to open connection to ' + str(get_setting_value('SMTP_SERVER')) + ':' + str(get_setting_value('SMTP_PORT'))])
|
||||||
|
|
||||||
|
if get_setting_value("LOG_LEVEL") == 'debug':
|
||||||
|
|
||||||
try:
|
|
||||||
send_email(msg,smtp_timeout)
|
send_email(msg,smtp_timeout)
|
||||||
|
|
||||||
except smtplib.SMTPAuthenticationError as e:
|
else:
|
||||||
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError)'])
|
|
||||||
mylog('none', [' ERROR: Double-check your SMTP_USER and SMTP_PASS settings.)'])
|
try:
|
||||||
mylog('none', [' ERROR: ', str(e)])
|
send_email(msg,smtp_timeout)
|
||||||
except smtplib.SMTPServerDisconnected as e:
|
|
||||||
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected)'])
|
except smtplib.SMTPAuthenticationError as e:
|
||||||
mylog('none', [' ERROR: ', str(e)])
|
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPAuthenticationError)'])
|
||||||
except socket.gaierror as e:
|
mylog('none', [' ERROR: Double-check your SMTP_USER and SMTP_PASS settings.)'])
|
||||||
mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror)'])
|
mylog('none', [' ERROR: ', str(e)])
|
||||||
mylog('none', [' ERROR: ', str(e)])
|
except smtplib.SMTPServerDisconnected as e:
|
||||||
except ssl.SSLError as e:
|
mylog('none', [' ERROR: Couldn\'t connect to the SMTP server (SMTPServerDisconnected)'])
|
||||||
mylog('none', [' ERROR: Could not establish SSL connection (ssl.SSLError)'])
|
mylog('none', [' ERROR: ', str(e)])
|
||||||
mylog('none', [' ERROR: Are you sure you need SMTP_FORCE_SSL enabled? Check your SMTP provider docs.'])
|
except socket.gaierror as e:
|
||||||
mylog('none', [' ERROR: ', str(e)])
|
mylog('none', [' ERROR: Could not resolve hostname (socket.gaierror)'])
|
||||||
|
mylog('none', [' ERROR: ', str(e)])
|
||||||
|
except ssl.SSLError as e:
|
||||||
|
mylog('none', [' ERROR: Could not establish SSL connection (ssl.SSLError)'])
|
||||||
|
mylog('none', [' ERROR: Are you sure you need SMTP_FORCE_SSL enabled? Check your SMTP provider docs.'])
|
||||||
|
mylog('none', [' ERROR: ', str(e)])
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------
|
||||||
def send_email(msg,smtp_timeout):
|
def send_email(msg,smtp_timeout):
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from plugin_utils import getPluginObject
|
|||||||
from plugin_helper import Plugin_Objects
|
from plugin_helper import Plugin_Objects
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value, bytes_to_string, sanitize_string, normalize_string
|
from helper import timeNowTZ, get_setting_value, bytes_to_string, sanitize_string, normalize_string
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB, get_device_stats
|
from database import DB, get_device_stats
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from const import confFileName, logPath
|
|||||||
from plugin_helper import Plugin_Objects, handleEmpty
|
from plugin_helper import Plugin_Objects, handleEmpty
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
|||||||
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402
|
from plugin_helper import Plugin_Objects, handleEmpty # noqa: E402
|
||||||
from logger import mylog, Logger # noqa: E402
|
from logger import mylog, Logger # noqa: E402
|
||||||
from helper import timeNowTZ, get_setting_value, hide_string # noqa: E402
|
from helper import timeNowTZ, get_setting_value, hide_string # noqa: E402
|
||||||
from notification import Notification_obj # noqa: E402
|
from models.notification_instance import NotificationInstance # noqa: E402
|
||||||
from database import DB # noqa: E402
|
from database import DB # noqa: E402
|
||||||
import conf
|
import conf
|
||||||
from const import confFileName, logPath
|
from const import confFileName, logPath
|
||||||
@@ -49,8 +49,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from const import confFileName, logPath
|
|||||||
from plugin_helper import Plugin_Objects, handleEmpty
|
from plugin_helper import Plugin_Objects, handleEmpty
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value, hide_string
|
from helper import timeNowTZ, get_setting_value, hide_string
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from const import confFileName, logPath
|
|||||||
from plugin_helper import Plugin_Objects
|
from plugin_helper import Plugin_Objects
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -51,8 +51,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from const import logPath, confFileName
|
|||||||
from plugin_helper import Plugin_Objects, handleEmpty
|
from plugin_helper import Plugin_Objects, handleEmpty
|
||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value, hide_string, write_file
|
from helper import timeNowTZ, get_setting_value, hide_string, write_file
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from database import DB
|
from database import DB
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -56,8 +56,8 @@ def main():
|
|||||||
# Initialize the Plugin obj output file
|
# Initialize the Plugin obj output file
|
||||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||||
|
|
||||||
# Create a Notification_obj instance
|
# Create a NotificationInstance instance
|
||||||
notifications = Notification_obj(db)
|
notifications = NotificationInstance(db)
|
||||||
|
|
||||||
# Retrieve new notifications
|
# Retrieve new notifications
|
||||||
new_notifications = notifications.getNew()
|
new_notifications = notifications.getNew()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
from database import DB
|
from database import DB
|
||||||
from models.device_instance import DeviceInstance
|
from models.device_instance import DeviceInstance
|
||||||
import conf
|
import conf
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
import conf
|
import conf
|
||||||
|
|
||||||
# Make sure the TIMEZONE for logging is correct
|
# Make sure the TIMEZONE for logging is correct
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
import conf
|
import conf
|
||||||
|
|
||||||
# Make sure the TIMEZONE for logging is correct
|
# Make sure the TIMEZONE for logging is correct
|
||||||
|
|||||||
@@ -243,6 +243,34 @@
|
|||||||
"string": "How many last <code>app.log</code> lines to keep. If <code>LOG_LEVEL</code> is set to <code>debug</code> the app generates about 10000 lines per hour, so when debugging an issue the recommended setting should cover the bug occurence timeframe. For example for a bug with a 3 day periodical appearence the value <code>1000000</code> should be sufficient. Setting this value to <code>1000000</code> generates approximatelly a 50MB <code>app.log</code> file. Set to <code>0</code> to disable log purging."
|
"string": "How many last <code>app.log</code> lines to keep. If <code>LOG_LEVEL</code> is set to <code>debug</code> the app generates about 10000 lines per hour, so when debugging an issue the recommended setting should cover the bug occurence timeframe. For example for a bug with a 3 day periodical appearence the value <code>1000000</code> should be sufficient. Setting this value to <code>1000000</code> generates approximatelly a 50MB <code>app.log</code> file. Set to <code>0</code> to disable log purging."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"function": "NOTI_LENGTH",
|
||||||
|
"type": {
|
||||||
|
"dataType": "integer",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"elementType": "input",
|
||||||
|
"elementOptions": [{ "type": "number" }],
|
||||||
|
"transformers": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_value": 0,
|
||||||
|
"options": [],
|
||||||
|
"localized": ["name", "description"],
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"language_code": "en_us",
|
||||||
|
"string": "Notifications history"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": [
|
||||||
|
{
|
||||||
|
"language_code": "en_us",
|
||||||
|
"string": "How many latest in-app Notification entries to keep. Set to <code>0</code> to disable."
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
|
|||||||
from logger import mylog, Logger, append_line_to_file
|
from logger import mylog, Logger, append_line_to_file
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from const import logPath, applicationPath
|
from const import logPath, applicationPath
|
||||||
|
from messaging.in_app import remove_old
|
||||||
import conf
|
import conf
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ def main():
|
|||||||
mylog('verbose', [f'[{pluginName}] In script'])
|
mylog('verbose', [f'[{pluginName}] In script'])
|
||||||
|
|
||||||
MAINT_LOG_LENGTH = int(get_setting_value('MAINT_LOG_LENGTH'))
|
MAINT_LOG_LENGTH = int(get_setting_value('MAINT_LOG_LENGTH'))
|
||||||
|
MAINT_NOTI_LENGTH = int(get_setting_value('MAINT_NOTI_LENGTH'))
|
||||||
|
|
||||||
# Check if set
|
# Check if set
|
||||||
if MAINT_LOG_LENGTH != 0:
|
if MAINT_LOG_LENGTH != 0:
|
||||||
@@ -63,7 +65,10 @@ def main():
|
|||||||
|
|
||||||
mylog('verbose', [f'[{pluginName}] Cleanup finished'])
|
mylog('verbose', [f'[{pluginName}] Cleanup finished'])
|
||||||
|
|
||||||
|
# Check if set
|
||||||
|
if MAINT_NOTI_LENGTH != 0:
|
||||||
|
mylog('verbose', [f'[{pluginName}] Cleaning in-app notification history'])
|
||||||
|
remove_old(MAINT_NOTI_LENGTH)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
from database import DB
|
from database import DB
|
||||||
from models.device_instance import DeviceInstance
|
from models.device_instance import DeviceInstance
|
||||||
import conf
|
import conf
|
||||||
|
|||||||
@@ -969,13 +969,13 @@
|
|||||||
"name": [
|
"name": [
|
||||||
{
|
{
|
||||||
"language_code": "en_us",
|
"language_code": "en_us",
|
||||||
"string": "Last Connection"
|
"string": "Last Seen"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": [
|
"description": [
|
||||||
{
|
{
|
||||||
"language_code": "en_us",
|
"language_code": "en_us",
|
||||||
"string": "The date and time of the last connection with the device. Uneditable - Autodetected."
|
"string": "The date and time of the last seen connection with the device. Uneditable - Autodetected."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1150,7 +1150,7 @@
|
|||||||
"description": [
|
"description": [
|
||||||
{
|
{
|
||||||
"language_code": "en_us",
|
"language_code": "en_us",
|
||||||
"string": "Indicates whether an alert should be triggered when the device goes down. The device has to be down for longet than the time set in the <b>Alert Down After</b> <code>NTFPRCS_alert_down_time</code> setting."
|
"string": "Indicates whether an alert should be triggered when the device goes down. The device has to be down for longer than the time set in the <b>Alert Down After</b> <code>NTFPRCS_alert_down_time</code> setting."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1633,4 +1633,4 @@
|
|||||||
],
|
],
|
||||||
"required": [],
|
"required": [],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
This plugin scans your network for open ports. Only IPs are scanned that are accessible by the app container.
|
This plugin scans your network for open ports. Only IPs are scanned that are accessible by the app container.
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
- TBD
|
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
- N/A
|

|
||||||
BIN
front/plugins/nmap_scan/nmap_ports_services.png
Executable file
BIN
front/plugins/nmap_scan/nmap_ports_services.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 161 KiB |
@@ -45,7 +45,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
import conf
|
import conf
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from logger import mylog, Logger
|
|||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from crypto_utils import encrypt_data
|
from crypto_utils import encrypt_data
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
import conf
|
import conf
|
||||||
from pytz import timezone
|
from pytz import timezone
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from plugin_utils import get_plugins_configs
|
|||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from const import pluginsPath, fullDbPath, logPath
|
from const import pluginsPath, fullDbPath, logPath
|
||||||
from helper import timeNowTZ, get_setting_value
|
from helper import timeNowTZ, get_setting_value
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
from database import DB
|
from database import DB
|
||||||
from models.device_instance import DeviceInstance
|
from models.device_instance import DeviceInstance
|
||||||
import conf
|
import conf
|
||||||
|
|||||||
@@ -54,16 +54,27 @@ def check_services_health(site):
|
|||||||
mylog('verbose', [f'[{pluginName}] Checking {site}'])
|
mylog('verbose', [f'[{pluginName}] Checking {site}'])
|
||||||
|
|
||||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resp = requests.get(site, verify=False, timeout=get_setting_value('WEBMON_RUN_TIMEOUT'))
|
resp = requests.get(site, verify=False, timeout=get_setting_value('WEBMON_RUN_TIMEOUT'))
|
||||||
latency = resp.elapsed.total_seconds()
|
latency = resp.elapsed.total_seconds()
|
||||||
status = resp.status_code
|
status = resp.status_code
|
||||||
except requests.exceptions.SSLError:
|
except SSLError:
|
||||||
status = 503
|
status = 495 # SSL Certificate Error (non-standard, but more meaningful than 503)
|
||||||
latency = 99999
|
latency = 99999
|
||||||
except:
|
mylog('debug', [f'[{pluginName}] SSL error while checking {site}'])
|
||||||
status = 503
|
except Timeout:
|
||||||
|
status = 504 # Gateway Timeout
|
||||||
latency = 99999
|
latency = 99999
|
||||||
|
mylog('debug', [f'[{pluginName}] Timeout while checking {site}'])
|
||||||
|
except RequestException as e:
|
||||||
|
status = 520 # Web server is returning an unknown error (Cloudflare-style)
|
||||||
|
latency = 99999
|
||||||
|
mylog('debug', [f'[{pluginName}] Request error while checking {site}: {e}'])
|
||||||
|
except Exception as e:
|
||||||
|
status = 500 # Internal Server Error (fallback)
|
||||||
|
latency = 99999
|
||||||
|
mylog('debug', [f'[{pluginName}] Unexpected error while checking {site}: {e}'])
|
||||||
|
|
||||||
mylog('verbose', [f'[{pluginName}] Result for {site} (status|latency) : {status}|{latency}'])
|
mylog('verbose', [f'[{pluginName}] Result for {site} (status|latency) : {status}|{latency}'])
|
||||||
|
|
||||||
|
|||||||
@@ -324,8 +324,15 @@ function initializeCalendar () {
|
|||||||
},
|
},
|
||||||
|
|
||||||
eventRender: function (event, element, view) {
|
eventRender: function (event, element, view) {
|
||||||
$(element).tooltip({container: 'body', placement: 'bottom', title: event.tooltip});
|
// $(element).tooltip({container: 'body', placement: 'bottom', title: event.tooltip});
|
||||||
// element.attr ('title', event.tooltip); // Alternative tooltip
|
tltp = event.tooltip.replace('\n',' | ')
|
||||||
|
|
||||||
|
element.attr ('title', tltp); // Alternative tooltip
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
eventClick: function(info) {
|
||||||
|
console.log(info);
|
||||||
},
|
},
|
||||||
|
|
||||||
loading: function( isLoading, view ) {
|
loading: function( isLoading, view ) {
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ require 'php/templates/header.php';
|
|||||||
if (result.includes("+")) { // Check if timezone offset is present
|
if (result.includes("+")) { // Check if timezone offset is present
|
||||||
result = result.split('+')[0]; // Remove timezone offset
|
result = result.split('+')[0]; // Remove timezone offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = localizeTimestamp(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ nav:
|
|||||||
- Reverse Proxy: REVERSE_PROXY.md
|
- Reverse Proxy: REVERSE_PROXY.md
|
||||||
- Webhooks (n8n): WEBHOOK_N8N.md
|
- Webhooks (n8n): WEBHOOK_N8N.md
|
||||||
- Workflows: WORKFLOWS.md
|
- Workflows: WORKFLOWS.md
|
||||||
|
- Docker Swarm: DOCKER_SWARM.md
|
||||||
- Help:
|
- Help:
|
||||||
- Common issues: COMMON_ISSUES.md
|
- Common issues: COMMON_ISSUES.md
|
||||||
- Random MAC: RANDOM_MAC.md
|
- Random MAC: RANDOM_MAC.md
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ from api import update_api
|
|||||||
from scan.session_events import process_scan
|
from scan.session_events import process_scan
|
||||||
from initialise import importConfigs
|
from initialise import importConfigs
|
||||||
from database import DB
|
from database import DB
|
||||||
from reporting import get_notifications
|
from messaging.reporting import get_notifications
|
||||||
from notification import Notification_obj
|
from models.notification_instance import NotificationInstance
|
||||||
from plugin import plugin_manager
|
from plugin import plugin_manager
|
||||||
from scan.device_handling import update_devices_names
|
from scan.device_handling import update_devices_names
|
||||||
from workflows.manager import WorkflowManager
|
from workflows.manager import WorkflowManager
|
||||||
@@ -172,7 +172,7 @@ def main ():
|
|||||||
final_json = get_notifications(db)
|
final_json = get_notifications(db)
|
||||||
|
|
||||||
# Write the notifications into the DB
|
# Write the notifications into the DB
|
||||||
notification = Notification_obj(db)
|
notification = NotificationInstance(db)
|
||||||
notificationObj = notification.create(final_json, "")
|
notificationObj = notification.create(final_json, "")
|
||||||
|
|
||||||
# run all enabled publisher gateways
|
# run all enabled publisher gateways
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ from const import (apiPath, sql_appevents, sql_devices_all, sql_events_pending_a
|
|||||||
from logger import mylog
|
from logger import mylog
|
||||||
from helper import write_file, get_setting_value, timeNowTZ
|
from helper import write_file, get_setting_value, timeNowTZ
|
||||||
from app_state import updateState
|
from app_state import updateState
|
||||||
from user_events_queue import UserEventsQueue
|
from models.user_events_queue_instance import UserEventsQueueInstance
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
|
|
||||||
# Import the start_server function
|
# Import the start_server function
|
||||||
from graphql_server.graphql_server_start import start_server
|
from graphql_server.graphql_server_start import start_server
|
||||||
@@ -147,7 +147,7 @@ class api_endpoint_class:
|
|||||||
# Update user event execution log
|
# Update user event execution log
|
||||||
# mylog('verbose', [f'[API] api_endpoint_class: is_ad_hoc_user_event {self.is_ad_hoc_user_event}'])
|
# mylog('verbose', [f'[API] api_endpoint_class: is_ad_hoc_user_event {self.is_ad_hoc_user_event}'])
|
||||||
if self.is_ad_hoc_user_event:
|
if self.is_ad_hoc_user_event:
|
||||||
execution_log = UserEventsQueue()
|
execution_log = UserEventsQueueInstance()
|
||||||
execution_log.finalize_event("update_api")
|
execution_log.finalize_event("update_api")
|
||||||
self.is_ad_hoc_user_event = False
|
self.is_ad_hoc_user_event = False
|
||||||
|
|
||||||
|
|||||||
@@ -120,12 +120,10 @@ class Query(ObjectType):
|
|||||||
device["devIsRandomMac"] = 1 if is_random_mac(device["devMac"]) else 0
|
device["devIsRandomMac"] = 1 if is_random_mac(device["devMac"]) else 0
|
||||||
device["devParentChildrenCount"] = get_number_of_children(device["devMac"], devices_data)
|
device["devParentChildrenCount"] = get_number_of_children(device["devMac"], devices_data)
|
||||||
device["devIpLong"] = format_ip_long(device.get("devLastIP", ""))
|
device["devIpLong"] = format_ip_long(device.get("devLastIP", ""))
|
||||||
|
|
||||||
|
|
||||||
mylog('verbose', f'[graphql_schema] devices_data: {devices_data}')
|
mylog('verbose', f'[graphql_schema] devices_data: {devices_data}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Apply sorting if options are provided
|
# Apply sorting if options are provided
|
||||||
if options:
|
if options:
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ sys.path.extend([f"{INSTALL_PATH}/server"])
|
|||||||
from logger import mylog
|
from logger import mylog
|
||||||
from helper import get_setting_value, timeNowTZ
|
from helper import get_setting_value, timeNowTZ
|
||||||
from app_state import updateState
|
from app_state import updateState
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
|
|
||||||
# Flask application
|
# Flask application
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from api import update_api
|
|||||||
from scheduler import schedule_class
|
from scheduler import schedule_class
|
||||||
from plugin import plugin_manager, print_plugin_info
|
from plugin import plugin_manager, print_plugin_info
|
||||||
from plugin_utils import get_plugins_configs, get_set_value_for_init
|
from plugin_utils import get_plugins_configs, get_set_value_for_init
|
||||||
from notification import write_notification
|
from messaging.in_app import write_notification
|
||||||
from crypto_utils import get_random_bytes
|
from crypto_utils import get_random_bytes
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|||||||
105
server/messaging/in_app.py
Executable file
105
server/messaging/in_app.py
Executable file
@@ -0,0 +1,105 @@
|
|||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import _io
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
from yattag import indent
|
||||||
|
from json2table import convert
|
||||||
|
|
||||||
|
# Register NetAlertX directories
|
||||||
|
INSTALL_PATH="/app"
|
||||||
|
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
|
# Register NetAlertX modules
|
||||||
|
|
||||||
|
import conf
|
||||||
|
from const import applicationPath, logPath, apiPath, confFileName, reportTemplatesPath
|
||||||
|
from logger import logResult, mylog
|
||||||
|
from helper import generate_mac_links, removeDuplicateNewLines, timeNowTZ, get_file_content, write_file, get_setting_value, get_timezone_offset
|
||||||
|
|
||||||
|
NOTIFICATION_API_FILE = apiPath + 'user_notifications.json'
|
||||||
|
|
||||||
|
# Show Frontend User Notification
|
||||||
|
def write_notification(content, level, timestamp):
|
||||||
|
|
||||||
|
# Generate GUID
|
||||||
|
guid = str(uuid.uuid4())
|
||||||
|
|
||||||
|
# Prepare notification dictionary
|
||||||
|
notification = {
|
||||||
|
'timestamp': str(timestamp),
|
||||||
|
'guid': guid,
|
||||||
|
'read': 0,
|
||||||
|
'level': level,
|
||||||
|
'content': content
|
||||||
|
}
|
||||||
|
|
||||||
|
# If file exists, load existing data, otherwise initialize as empty list
|
||||||
|
if os.path.exists(NOTIFICATION_API_FILE):
|
||||||
|
with open(NOTIFICATION_API_FILE, 'r') as file:
|
||||||
|
# Check if the file object is of type _io.TextIOWrapper
|
||||||
|
if isinstance(file, _io.TextIOWrapper):
|
||||||
|
file_contents = file.read() # Read file contents
|
||||||
|
if file_contents == '':
|
||||||
|
file_contents = '[]' # If file is empty, initialize as empty list
|
||||||
|
|
||||||
|
# mylog('debug', ['[Notification] User Notifications file: ', file_contents])
|
||||||
|
notifications = json.loads(file_contents) # Parse JSON data
|
||||||
|
else:
|
||||||
|
mylog('none', '[Notification] File is not of type _io.TextIOWrapper')
|
||||||
|
notifications = []
|
||||||
|
else:
|
||||||
|
notifications = []
|
||||||
|
|
||||||
|
# Append new notification
|
||||||
|
notifications.append(notification)
|
||||||
|
|
||||||
|
# Write updated data back to file
|
||||||
|
with open(NOTIFICATION_API_FILE, 'w') as file:
|
||||||
|
json.dump(notifications, file, indent=4)
|
||||||
|
|
||||||
|
# Trim notifications
|
||||||
|
def remove_old(keepNumberOfEntries):
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if not os.path.exists(NOTIFICATION_API_FILE):
|
||||||
|
mylog('info', '[Notification] No notifications file to clean.')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Load existing notifications
|
||||||
|
try:
|
||||||
|
with open(NOTIFICATION_API_FILE, 'r') as file:
|
||||||
|
file_contents = file.read().strip()
|
||||||
|
if file_contents == '':
|
||||||
|
notifications = []
|
||||||
|
else:
|
||||||
|
notifications = json.loads(file_contents)
|
||||||
|
except Exception as e:
|
||||||
|
mylog('none', f'[Notification] Error reading notifications file: {e}')
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(notifications, list):
|
||||||
|
mylog('none', '[Notification] Invalid format: not a list')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Sort by timestamp descending
|
||||||
|
try:
|
||||||
|
notifications.sort(key=lambda x: x['timestamp'], reverse=True)
|
||||||
|
except KeyError:
|
||||||
|
mylog('none', '[Notification] Missing timestamp in one or more entries')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Trim to the latest entries
|
||||||
|
trimmed = notifications[:keepNumberOfEntries]
|
||||||
|
|
||||||
|
# Write back the trimmed list
|
||||||
|
try:
|
||||||
|
with open(NOTIFICATION_API_FILE, 'w') as file:
|
||||||
|
json.dump(trimmed, file, indent=4)
|
||||||
|
mylog('verbose', f'[Notification] Trimmed notifications to latest {keepNumberOfEntries}')
|
||||||
|
except Exception as e:
|
||||||
|
mylog('none', f'Error writing trimmed notifications file: {e}')
|
||||||
@@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Register NetAlertX directories
|
||||||
|
INSTALL_PATH="/app"
|
||||||
|
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
import conf
|
import conf
|
||||||
from const import applicationPath, logPath, apiPath, confFileName
|
from const import applicationPath, logPath, apiPath, confFileName
|
||||||
@@ -2,6 +2,7 @@ import datetime
|
|||||||
import os
|
import os
|
||||||
import _io
|
import _io
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -9,16 +10,22 @@ import requests
|
|||||||
from yattag import indent
|
from yattag import indent
|
||||||
from json2table import convert
|
from json2table import convert
|
||||||
|
|
||||||
|
# Register NetAlertX directories
|
||||||
|
INSTALL_PATH="/app"
|
||||||
|
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
# Register NetAlertX modules
|
# Register NetAlertX modules
|
||||||
import conf
|
import conf
|
||||||
from const import applicationPath, logPath, apiPath, confFileName, reportTemplatesPath
|
from const import applicationPath, logPath, apiPath, confFileName, reportTemplatesPath
|
||||||
from logger import logResult, mylog
|
from logger import logResult, mylog
|
||||||
from helper import generate_mac_links, removeDuplicateNewLines, timeNowTZ, get_file_content, write_file, get_setting_value, get_timezone_offset
|
from helper import generate_mac_links, removeDuplicateNewLines, timeNowTZ, get_file_content, write_file, get_setting_value, get_timezone_offset
|
||||||
|
from messaging.in_app import write_notification
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Notification object handling
|
# Notification object handling
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
class Notification_obj:
|
class NotificationInstance:
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
@@ -290,45 +297,7 @@ class Notification_obj:
|
|||||||
# Reporting
|
# Reporting
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
# Handle Frontend User Notifications
|
|
||||||
def write_notification(content, level, timestamp):
|
|
||||||
NOTIFICATION_API_FILE = apiPath + 'user_notifications.json'
|
|
||||||
|
|
||||||
# Generate GUID
|
|
||||||
guid = str(uuid.uuid4())
|
|
||||||
|
|
||||||
# Prepare notification dictionary
|
|
||||||
notification = {
|
|
||||||
'timestamp': str(timestamp),
|
|
||||||
'guid': guid,
|
|
||||||
'read': 0,
|
|
||||||
'level': level,
|
|
||||||
'content': content
|
|
||||||
}
|
|
||||||
|
|
||||||
# If file exists, load existing data, otherwise initialize as empty list
|
|
||||||
if os.path.exists(NOTIFICATION_API_FILE):
|
|
||||||
with open(NOTIFICATION_API_FILE, 'r') as file:
|
|
||||||
# Check if the file object is of type _io.TextIOWrapper
|
|
||||||
if isinstance(file, _io.TextIOWrapper):
|
|
||||||
file_contents = file.read() # Read file contents
|
|
||||||
if file_contents == '':
|
|
||||||
file_contents = '[]' # If file is empty, initialize as empty list
|
|
||||||
|
|
||||||
# mylog('debug', ['[Notification] User Notifications file: ', file_contents])
|
|
||||||
notifications = json.loads(file_contents) # Parse JSON data
|
|
||||||
else:
|
|
||||||
mylog('error', 'File is not of type _io.TextIOWrapper')
|
|
||||||
notifications = []
|
|
||||||
else:
|
|
||||||
notifications = []
|
|
||||||
|
|
||||||
# Append new notification
|
|
||||||
notifications.append(notification)
|
|
||||||
|
|
||||||
# Write updated data back to file
|
|
||||||
with open(NOTIFICATION_API_FILE, 'w') as file:
|
|
||||||
json.dump(notifications, file, indent=4)
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
def construct_notifications(JSON, section):
|
def construct_notifications(JSON, section):
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Register NetAlertX directories
|
||||||
|
INSTALL_PATH="/app"
|
||||||
|
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
# Register NetAlertX modules
|
# Register NetAlertX modules
|
||||||
from const import pluginsPath, logPath, applicationPath, reportTemplatesPath
|
from const import pluginsPath, logPath, applicationPath, reportTemplatesPath
|
||||||
from logger import mylog
|
from logger import mylog
|
||||||
|
|
||||||
class UserEventsQueue:
|
class UserEventsQueueInstance:
|
||||||
"""
|
"""
|
||||||
Handles the execution queue log file, allowing reading, writing,
|
Handles the execution queue log file, allowing reading, writing,
|
||||||
and removing processed events.
|
and removing processed events.
|
||||||
@@ -30,7 +35,7 @@ class UserEventsQueue:
|
|||||||
Returns an empty list if the file doesn't exist.
|
Returns an empty list if the file doesn't exist.
|
||||||
"""
|
"""
|
||||||
if not os.path.exists(self.log_file):
|
if not os.path.exists(self.log_file):
|
||||||
mylog('none', ['[UserEventsQueue] Log file not found: ', self.log_file])
|
mylog('none', ['[UserEventsQueueInstance] Log file not found: ', self.log_file])
|
||||||
return [] # No log file, return empty list
|
return [] # No log file, return empty list
|
||||||
with open(self.log_file, "r") as file:
|
with open(self.log_file, "r") as file:
|
||||||
return file.readlines()
|
return file.readlines()
|
||||||
@@ -72,7 +77,7 @@ class UserEventsQueue:
|
|||||||
self.write_log(updated_lines)
|
self.write_log(updated_lines)
|
||||||
|
|
||||||
|
|
||||||
mylog('minimal', ['[UserEventsQueue] Processed event: ', event])
|
mylog('minimal', ['[UserEventsQueueInstance] Processed event: ', event])
|
||||||
|
|
||||||
return removed
|
return removed
|
||||||
|
|
||||||
@@ -16,11 +16,11 @@ from helper import timeNowTZ, get_file_content, write_file, get_setting, get_set
|
|||||||
from app_state import updateState
|
from app_state import updateState
|
||||||
from api import update_api
|
from api import update_api
|
||||||
from plugin_utils import logEventStatusCounts, get_plugin_string, get_plugin_setting_obj, print_plugin_info, list_to_csv, combine_plugin_objects, resolve_wildcards_arr, handle_empty, custom_plugin_decoder, decode_and_rename_files
|
from plugin_utils import logEventStatusCounts, get_plugin_string, get_plugin_setting_obj, print_plugin_info, list_to_csv, combine_plugin_objects, resolve_wildcards_arr, handle_empty, custom_plugin_decoder, decode_and_rename_files
|
||||||
from notification import Notification_obj, write_notification
|
from models.notification_instance import NotificationInstance
|
||||||
from user_events_queue import UserEventsQueue
|
from messaging.in_app import write_notification
|
||||||
|
from models.user_events_queue_instance import UserEventsQueueInstance
|
||||||
from crypto_utils import generate_deterministic_guid
|
from crypto_utils import generate_deterministic_guid
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
class plugin_manager:
|
class plugin_manager:
|
||||||
def __init__(self, db, all_plugins):
|
def __init__(self, db, all_plugins):
|
||||||
@@ -79,7 +79,7 @@ class plugin_manager:
|
|||||||
"""
|
"""
|
||||||
Process user events from the execution queue log file and notify the user about executed events.
|
Process user events from the execution queue log file and notify the user about executed events.
|
||||||
"""
|
"""
|
||||||
execution_log = UserEventsQueue()
|
execution_log = UserEventsQueueInstance()
|
||||||
|
|
||||||
# Track whether to show notification for executed events
|
# Track whether to show notification for executed events
|
||||||
executed_events = []
|
executed_events = []
|
||||||
@@ -102,11 +102,11 @@ class plugin_manager:
|
|||||||
|
|
||||||
# Process each event type
|
# Process each event type
|
||||||
if event == 'test':
|
if event == 'test':
|
||||||
handle_test(param)
|
self.handle_test(param)
|
||||||
executed_events.append(f"test with param {param}")
|
executed_events.append(f"test with param {param}")
|
||||||
execution_log.finalize_event("test")
|
execution_log.finalize_event("test")
|
||||||
elif event == 'run':
|
elif event == 'run':
|
||||||
handle_run(param)
|
self.handle_run(param)
|
||||||
executed_events.append(f"run with param {param}")
|
executed_events.append(f"run with param {param}")
|
||||||
execution_log.finalize_event("run")
|
execution_log.finalize_event("run")
|
||||||
elif event == 'update_api':
|
elif event == 'update_api':
|
||||||
@@ -151,11 +151,11 @@ class plugin_manager:
|
|||||||
sample_json = json.loads(get_file_content(reportTemplatesPath + 'webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"]
|
sample_json = json.loads(get_file_content(reportTemplatesPath + 'webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"]
|
||||||
|
|
||||||
# Create fake notification
|
# Create fake notification
|
||||||
notification = Notification_obj(db)
|
notification = NotificationInstance(self.db)
|
||||||
notificationObj = notification.create(sample_json, "")
|
notificationObj = notification.create(sample_json, "")
|
||||||
|
|
||||||
# Run test
|
# Run test
|
||||||
handle_run(runType)
|
self.handle_run(runType)
|
||||||
|
|
||||||
# Remove sample notification
|
# Remove sample notification
|
||||||
notificationObj.remove(notificationObj.GUID)
|
notificationObj.remove(notificationObj.GUID)
|
||||||
@@ -562,7 +562,7 @@ def execute_plugin(db, all_plugins, plugin ):
|
|||||||
endpoints = ["plugins_events","plugins_objects", "plugins_history", "appevents"]
|
endpoints = ["plugins_events","plugins_objects", "plugins_history", "appevents"]
|
||||||
|
|
||||||
# check if we need to update devices api endpoint as well to prevent long user waits on Loading...
|
# check if we need to update devices api endpoint as well to prevent long user waits on Loading...
|
||||||
userUpdatedDevices = UserEventsQueue().has_update_devices
|
userUpdatedDevices = UserEventsQueueInstance().has_update_devices
|
||||||
if userUpdatedDevices:
|
if userUpdatedDevices:
|
||||||
endpoints += ["devices"]
|
endpoints += ["devices"]
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import conf
|
|||||||
from scan.device_handling import create_new_devices, print_scan_stats, save_scanned_devices, update_devices_data_from_scan, exclude_ignored_devices
|
from scan.device_handling import create_new_devices, print_scan_stats, save_scanned_devices, update_devices_data_from_scan, exclude_ignored_devices
|
||||||
from helper import timeNowTZ
|
from helper import timeNowTZ
|
||||||
from logger import mylog
|
from logger import mylog
|
||||||
from reporting import skip_repeated_notifications
|
from messaging.reporting import skip_repeated_notifications
|
||||||
|
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user