diff --git a/README.md b/README.md index b2cbec36..d20dcd3b 100755 --- a/README.md +++ b/README.md @@ -44,8 +44,9 @@ Extend the app if you want to create your own scanner and handle the results and | Docs | Link | |-------------|-------------| -| 📥 | [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) (HW install not supported, but might be possible - submit a PR🙏 or start a discussion) | -| 📚 | [All Documentation](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/README.md) (App Usage and Configuration) | +| 📥🐳 | [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) +| 📥💻 | [HW install (experimental 🧪)](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HW_INSTALL.md) | +| 📚 | [All Documentation](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/README.md) (App Usage and Configuration) | > Other Alternatives > diff --git a/back/install.sh b/back/install.sh new file mode 100755 index 00000000..8471ba20 --- /dev/null +++ b/back/install.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# Check if script is run as root +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root. Please use 'sudo'." + exit 1 +fi + +# Set environment variables +PORT=20211 +INSTALL_DIR=/home/pi # Specify the installation directory here + +# Update and upgrade system packages +# apt-get update +# apt-get upgrade -y + +# Install Git +apt-get install -y git + +# Clone the application repository +git clone https://github.com/jokob-sk/Pi.Alert "$INSTALL_DIR/pialert" + +# Install dependencies +apt-get install -y \ + tini snmp ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo \ + nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools \ + python3 iproute2 nmap python3-pip zip systemctl usbutils traceroute + +# --------------------------------------------------------------- +# alternate dependencies +sudo apt-get install -y \ + nginx nginx-core mtr mtr-tiny php-fpm php7.4-fpm + +sudo apt install php-cli php8.2 php8.2-fpm -y +sudo apt install php-cli php7.4 php7.4-fpm -y + +sudo apt install php7.4-sqlite3 -y + +sudo phpenmod -v 7.4 sqlite3 +sudo apt install net-tools -y + +curl -sSL https://bootstrap.pypa.io/get-pip.py | python3 +# --------------------------------------------------------------- + +# Install Python packages +pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi + +# Update alternatives for Python +update-alternatives --install /usr/bin/python python /usr/bin/python3 10 + +# Configure Nginx +echo "Configure Nginx" +echo "---------------------------------------------------------------" + + +sudo rm -R /var/www/html +ln -s $INSTALL_DIR/pialert/front /var/www/html +sudo rm /etc/nginx/sites-available/default +sudo ln -s "$INSTALL_DIR/pialert/install/default" /etc/nginx/sites-available/default +sudo sed -i 's/listen 80/listen '"$PORT"'/g' /etc/nginx/sites-available/default + +echo "Run the hardware vendors update" +echo "---------------------------------------------------------------" +# Run the hardware vendors update +"$INSTALL_DIR/pialert/back/update_vendors.sh" + +# Create a backup of pialert.conf +cp "$INSTALL_DIR/pialert/config/pialert.conf" "$INSTALL_DIR/pialert/back/pialert.conf_bak" + +# Create a backup of pialert.db +cp "$INSTALL_DIR/pialert/db/pialert.db" "$INSTALL_DIR/pialert/back/pialert.db_bak" + +# Create buildtimestamp.txt +date +%s > "$INSTALL_DIR/pialert/front/buildtimestamp.txt" + +chmod -R a+rwx $INSTALL_DIR +chmod -R a+rwx /var/www/html +chmod -R a+rw $INSTALL_DIR/front/log +chmod -R a+rw $INSTALL_DIR/config + +/etc/init.d/php7.4-fpm start +# /etc/init.d/php8.2-fpm start +/etc/init.d/nginx start + +# Start Nginx and your application to start at boot (if needed) +systemctl start nginx +systemctl enable nginx +systemctl enable pi-alert +sudo systemctl restart nginx + +# Provide instructions or additional setup if needed +echo "Installation completed. Please configure any additional settings for your application." + + +cd $INSTALL_DIR/pialert + +"$INSTALL_DIR/pialert/dockerfiles/start.sh" + +# Exit the script +exit 0 diff --git a/docs/DEVICES_BULK_EDITING.md b/docs/DEVICES_BULK_EDITING.md old mode 100644 new mode 100755 diff --git a/docs/HW_INSTALL.md b/docs/HW_INSTALL.md new file mode 100644 index 00000000..3f23a6e1 --- /dev/null +++ b/docs/HW_INSTALL.md @@ -0,0 +1,29 @@ +# How to install PiAlert on the server hardware + +To download and install PiAlert on the hardware/server directly use `curl` or `wget` commands. + +> [!NOTE] +> This is an Experimental feature 🧪 and it relies on community support. + +PiAlert will be installed in `home/pi/pialert/` and run on port number `20211`. + +## CURL + +```bash +curl -o install.sh https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/install/install.sh +chmod +x install.sh +./install.sh +``` + +## WGET + + +```bash +wget https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/install/install.sh +chmod +x install.sh +./install.sh +``` + +These commands will download the `install.sh` script from the GitHub repository, make it executable with `chmod`, and then run it using `./install.sh`. + +Make sure you have the necessary permissions to execute the script. \ No newline at end of file diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index e04ae4ab..a3eaa753 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -478,7 +478,7 @@ "ENABLE_PLUGINS_name" : "Enable Plugins", "ENABLE_PLUGINS_description" : "Enables the plugins functionality. Loading plugins requires more hardware resources so you might want to disable them on low-powered system.", "PLUGINS_KEEP_HIST_name" : "Plugins History", - "PLUGINS_KEEP_HIST_description" : "How many entries of Plugins History scan results should be kept (globally, not device specific!).", + "PLUGINS_KEEP_HIST_description" : "How many entries of Plugins History scan results should be kept (per Plugin, not device specific).", "PIALERT_WEB_PROTECTION_name" : "Enable login", "PIALERT_WEB_PROTECTION_description" : "When enabled a login dialog is displayed. Read below carefully if you get locked out of your instance.", "PIALERT_WEB_PASSWORD_name" : "Login password", diff --git a/front/plugins/events_notifications/config.json b/front/plugins/events_notifications/config.json new file mode 100755 index 00000000..f704baa4 --- /dev/null +++ b/front/plugins/events_notifications/config.json @@ -0,0 +1,838 @@ +{ + "code_name": "events_notifications", + "plugin_type": "flow", + "template_type": "database-entry", + "unique_prefix": "EVNTNTF", + "enabled": true, + "data_source": "template", + "show_ui": false, + "localized": [ + "display_name", + "description", + "icon" + ], + "display_name": [ + { + "language_code": "en_us", + "string": "Known Devices" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The template used for known devices." + } + ], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "params": [ + { + "name": "target_macs", + "type": "setting", + "value": "KNWN_target_macs" + }, + { + "name": "dev_AlertDeviceDown", + "type": "setting", + "value": "KNWN_dev_AlertDeviceDown" + }, + { + "name": "dev_AlertEvents", + "type": "setting", + "value": "KNWN_dev_AlertEvents" + }, + { + "name": "trigger_ids", + "type": "array", + "value": "trigger.Object_PrimaryID" + }, + { + "name": "trigger_objects", + "type": "array", + "value": "trigger" + } + ], + "settings": [ + { + "function": "FLOW", + "type": "json", + "default_value": [ + { + "name": "send_notification", + "trigger": [ + { + "object_event": "new", + "object_filter": "", + "object": "Events_Notifications" + } + ], + "steps": [ + { + "step_type": "wait", + "params": [ + { + "days": 0, + "hours": 0, + "minutes": 0, + "seconds": 30 + } + ] + }, + { + "step_type": "condition", + "params": [ + { + "left": { + "value": "triggers[0].object['dev_DeviceID']", + "use_quotes": true, + "js_template": "'{value}'.toString()" + }, + "operator": { + "value": "==", + "data_type": "string" + }, + "right": { + "value": "device_id_param", + "use_quotes": false, + "js_template": "'{value}'.toString()" + } + } + ] + }, + { + "step_type": "condition", + "params": [ + { + "left": { + "value": "check_event_repetition(device_id_param, event_type_param, repetition_count_param)", + "use_quotes": false, + "js_template": "{value}" + }, + "operator": { + "value": "==", + "data_type": "boolean" + }, + "right": { + "value": true, + "use_quotes": false, + "js_template": "{value}" + } + } + ] + }, + { + "step_type": "action", + "params": [ + { + "type": "run_plugin", + "params": { + "unique_prefix": "webhook" + } + } + ] + }, + { + "step_type": "action", + "params": [ + { + "type": "run_plugin", + "params": { + "unique_prefix": "mqtt" + } + } + ] + } + ] + } + ], + "options": [ + { + "name": [ + { + "language_code": "en_us", + "string": "Device ID Parameter" + } + ], + "type": "string", + "default_value": "1", + "localized": [ + "name" + ] + }, + { + "name": [ + { + "language_code": "en_us", + "string": "Event Type Parameter" + } + ], + "type": "string", + "default_value": "device_down", + "localized": [ + "name" + ] + }, + { + "name": [ + { + "language_code": "en_us", + "string": "Repetition Count Parameter" + } + ], + "type": "integer", + "default_value": 3, + "localized": [ + "name" + ] + } + ], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Plugin flow" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "This flow sends a notification after 30s every time a new event is logged." + } + ] + }, + { + "function": "target_macs", + "type": "list.readonly", + "maxLength": 50, + "default_value": [], + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Target devices" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The MAC address of the devices to update. Uneditable. This parameter is dynamically updated via a Flow." + } + ] + }, + { + "function": "CMD", + "type": "text", + "default_value": "UPDATE Devices SET dev_AlertDeviceDown = {KNWN_dev_AlertDeviceDown}, dev_AlertEvents = {KNWN_dev_AlertEvents} WHERE dev_MAC in ({target_macs})", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "UPDATE SQL" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "This SQL query is used to update target devices." + } + ] + }, + { + "function": "dev_Name", + "type": "readonly", + "maxLength": 50, + "default_value": "(unknown)", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Name" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The name of the device. Uneditable as internal functionality is dependent on specific new device names." + } + ] + }, + { + "function": "dev_Owner", + "type": "string", + "maxLength": 30, + "default_value": "House", + "override_value": { + "override": false + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Owner" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The owner of the device." + } + ] + }, + { + "function": "dev_DeviceType", + "type": "string", + "maxLength": 30, + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Type" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The type of the device." + } + ] + }, + { + "function": "dev_Vendor", + "type": "readonly", + "maxLength": 250, + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Vendor" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The vendor of the device. Uneditable - Autodetected." + } + ] + }, + { + "function": "dev_Favorite", + "type": "integer.checkbox", + "default_value": 0, + "override_value": { + "override": false + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Favorite Device" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether the device is marked as a favorite." + } + ] + }, + { + "function": "dev_Group", + "type": "string", + "maxLength": 10, + "default_value": "", + "override_value": { + "override": false + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Group" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The group to which the device belongs." + } + ] + }, + { + "function": "dev_Comments", + "type": "string", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Comments" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Additional comments or notes about the device." + } + ] + }, + { + "function": "dev_FirstConnection", + "type": "readonly", + "format": "date-time", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "First Connection" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The date and time of the first connection with the device. Uneditable - Autodetected." + } + ] + }, + { + "function": "dev_LastConnection", + "type": "readonly", + "format": "date-time", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Last Connection" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The date and time of the last connection with the device. Uneditable - Autodetected." + } + ] + }, + { + "function": "dev_LastIP", + "type": "readonly", + "maxLength": 50, + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Last IP" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The last known IP address of the device. Uneditable - Autodetected." + } + ] + }, + { + "function": "dev_StaticIP", + "type": "integer.checkbox", + "default_value": 1, + "override_value": { + "override": true + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Static IP" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether the device has a static IP address." + } + ] + }, + { + "function": "dev_ScanCycle", + "type": "integer.checkbox", + "default_value": 1, + "override_value": { + "override": true + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Scan Cycle" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The default value of the Scan device dropdown. Enable if newly discovered devices should be scanned." + } + ] + }, + { + "function": "dev_LogEvents", + "type": "integer.checkbox", + "default_value": 0, + "override_value": { + "override": false + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Log Events" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether events related to the device shouldbe logged." + } + ] + }, + { + "function": "dev_AlertEvents", + "type": "integer.checkbox", + "default_value": 0, + "override_value": { + "override": true + }, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Alert Events" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether events related to the device should trigger alerts. The default value of the Alert All Events checkbox." + } + ] + }, + { + "function": "dev_AlertDeviceDown", + "type": "integer.checkbox", + "default_value": 0, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Alert Device Down" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether an alert should be triggered when the device goes down. The default value of the Alert Down checkbox." + } + ] + }, + { + "function": "dev_SkipRepeated", + "type": "integer", + "default_value": 0, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Skip Repeated" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The default value of the Skip repeated notifications for dropdown. Enter number of hours for which repeated notifications should be ignored for. If you enter 0 then you get notified on all events." + } + ] + }, + { + "function": "dev_LastNotification", + "type": "readonly", + "format": "date-time", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Last Notification" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The date and time of the last notification sent for the device. Uneditable - Autodetected." + } + ] + }, + { + "function": "dev_PresentLastScan", + "type": "integer.checkbox", + "default_value": 1, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Present Last Scan" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether the device should be marked as present after detected in a scan." + } + ] + }, + { + "function": "dev_NewDevice", + "type": "integer.checkbox", + "default_value": true, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "New Device" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether the device is considered a new device. The default value of the New Device checkbox." + } + ] + }, + { + "function": "dev_Location", + "type": "string", + "maxLength": 250, + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Location" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The location of the device." + } + ] + }, + { + "function": "dev_Archived", + "type": "integer.checkbox", + "default_value": 0, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Archived" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Indicates whether the device is archived. The default value of the Archived checkbox." + } + ] + }, + { + "function": "dev_Network_Node_MAC_ADDR", + "type": "string", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Network Node MAC Address" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The MAC address of the network node." + } + ] + }, + { + "function": "dev_Network_Node_port", + "type": "readonly", + "default_value": 0, + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Network Node Port" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The port number of the network node. Uneditable." + } + ] + }, + { + "function": "dev_Icon", + "type": "string", + "default_value": "", + "options": [], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Device Icon" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "The icon associated with the device. Check the documentation on icons for more details." + } + ] + } + ], + "required": [ + "dev_MAC", + "dev_Name", + "dev_Owner", + "dev_FirstConnection", + "dev_LastConnection", + "dev_LastIP", + "dev_StaticIP", + "dev_ScanCycle", + "dev_LogEvents", + "dev_AlertEvents", + "dev_AlertDeviceDown", + "dev_SkipRepeated", + "dev_LastNotification", + "dev_PresentLastScan", + "dev_NewDevice", + "dev_Location", + "dev_Archived", + "dev_Network_Node_MAC_ADDR", + "dev_Network_Node_port", + "dev_Icon" + ], + "additionalProperties": false +} \ No newline at end of file diff --git a/front/plugins/events_notifications/ignore_plugin b/front/plugins/events_notifications/ignore_plugin new file mode 100755 index 00000000..77ffa1c1 --- /dev/null +++ b/front/plugins/events_notifications/ignore_plugin @@ -0,0 +1 @@ +This plugin will not be loaded \ No newline at end of file diff --git a/front/plugins/known_template/config.json b/front/plugins/known_template/config.json index c42022d5..295a907d 100755 --- a/front/plugins/known_template/config.json +++ b/front/plugins/known_template/config.json @@ -1,5 +1,5 @@ { - "code_name": "Devices.known", + "code_name": "known_template", "template_type": "database-entry", "unique_prefix": "KNWN", "enabled": true, @@ -56,7 +56,8 @@ "trigger": [ { "object_event": "new", - "object_filter": "" + "object_filter": "", + "object": "Devices" } ], "steps": [ diff --git a/front/plugins/vendor_update/README.md b/front/plugins/vendor_update/README.md index 80ef4d8d..89cee0bd 100755 --- a/front/plugins/vendor_update/README.md +++ b/front/plugins/vendor_update/README.md @@ -1,6 +1,6 @@ ## Overview -A plugin to retrieve a MAC and vendor database to identify vendors for devices. +A plugin to retrieve a MAC and vendor database to identify vendors for devices. The Plugin result objects will be a list of vendors mapped to the devices where the vendor was previously unknown. ### Usage diff --git a/front/plugins/vendor_update/config.json b/front/plugins/vendor_update/config.json index 024dec7f..57d6b38b 100755 --- a/front/plugins/vendor_update/config.json +++ b/front/plugins/vendor_update/config.json @@ -106,7 +106,7 @@ { "function": "RUN_SCHD", "type": "text", - "default_value": "0 4 * * *", + "default_value": "0 4 * * 3", "options": [], "localized": [ "name", @@ -208,11 +208,7 @@ "description": [ { "language_code": "en_us", - "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect. " - }, - { - "language_code": "es_es", - "string": "Envíe una notificación si los valores seleccionados cambian. Use CTRL + Click para seleccionar/deseleccionar. " + "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect. " } ] }, diff --git a/front/plugins/vendor_update/script.py b/front/plugins/vendor_update/script.py index 4837f055..d61f0395 100755 --- a/front/plugins/vendor_update/script.py +++ b/front/plugins/vendor_update/script.py @@ -106,10 +106,10 @@ def update_vendors (dbPath, plugin_objects): ignored += 1 else : plugin_objects.add_object( - primaryId = device[0], # MAC (Device Name) - secondaryId = device[1], # IP Address (always 0.0.0.0) + primaryId = device[0], # MAC (Device Name) + secondaryId = device[1], # IP Address (always 0.0.0.0) watched1 = vendor, - watched2 = device[2], + watched2 = device[2], # Device name watched3 = "", watched4 = "", extra = "", diff --git a/install/default b/install/default index ea65dcc2..c00f025e 100755 --- a/install/default +++ b/install/default @@ -4,13 +4,16 @@ server { index index.php; rewrite /pialert/(.*) / permanent; - location ~* \.php$ { - fastcgi_pass unix:/run/php/php7.4-fpm.sock; - include fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param SCRIPT_NAME $fastcgi_script_name; - fastcgi_connect_timeout 75; - fastcgi_send_timeout 600; - fastcgi_read_timeout 600; - } + location ~* \.php$ { + set $php_version "7.4"; # Default PHP version + + # Use the selected PHP version + fastcgi_pass unix:/run/php/php$php_version-fpm.sock; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_connect_timeout 75; + fastcgi_send_timeout 600; + fastcgi_read_timeout 600; + } } \ No newline at end of file diff --git a/pialert/__main__.py b/pialert/__main__.py index c59e1f7c..679d5df5 100755 --- a/pialert/__main__.py +++ b/pialert/__main__.py @@ -29,7 +29,8 @@ from api import update_api from networkscan import process_scan from initialise import importConfigs from database import DB, get_all_devices -from reporting import check_and_run_event, send_notifications +from reporting import send_notifications +from plugin_utils import check_and_run_user_event from plugin import run_plugin_scripts @@ -52,7 +53,7 @@ main structure of Pi Alert run plugins (scheduled) processing scan results run plugins (after Scan) - reporting + reporting - could be replaced by run flows TODO end loop """ @@ -98,7 +99,7 @@ def main (): conf.plugins_once_run = True # check if there is a front end initiated event which needs to be executed - pluginsState = check_and_run_event(db, pluginsState) + pluginsState = check_and_run_user_event(db, pluginsState) # Update API endpoints update_api(db) diff --git a/pialert/plugin_utils.py b/pialert/plugin_utils.py index 8f95164a..6ac61b24 100755 --- a/pialert/plugin_utils.py +++ b/pialert/plugin_utils.py @@ -182,4 +182,88 @@ def handle_empty(value): if value == '' or value is None: value = 'null' - return value \ No newline at end of file + return value + + +#=============================================================================== +# Handling of user initialized front-end events +#=============================================================================== + +#------------------------------------------------------------------------------- +def check_and_run_user_event(db, pluginsState): + + sql = db.sql # TO-DO + sql.execute(""" select * from Parameters where par_ID = "Front_Event" """) + rows = sql.fetchall() + + event, param = ['',''] + if len(rows) > 0 and rows[0]['par_Value'] != 'finished': + keyValue = rows[0]['par_Value'].split('|') + + if len(keyValue) == 2: + event = keyValue[0] + param = keyValue[1] + else: + return pluginsState + + if event == 'test': + handle_test(param) + if event == 'run': + pluginsState = handle_run(param, db, pluginsState) + + # clear event execution flag + sql.execute ("UPDATE Parameters SET par_Value='finished' WHERE par_ID='Front_Event'") + + # commit to DB + db.commitDB() + + mylog('debug', [f'[MAIN] processScan3: {pluginsState.processScan}']) + + return pluginsState + +#------------------------------------------------------------------------------- +def handle_run(runType, db, pluginsState): + + mylog('minimal', ['[', timeNowTZ(), '] START Run: ', runType]) + + # run the plugin to run + for plugin in conf.plugins: + if plugin["unique_prefix"] == runType: + pluginsState = execute_plugin(db, plugin, pluginsState) + + mylog('minimal', ['[', timeNowTZ(), '] END Run: ', runType]) + return pluginsState + + + +#------------------------------------------------------------------------------- +def handle_test(testType): + + mylog('minimal', ['[', timeNowTZ(), '] START Test: ', testType]) + + # Open text sample + sample_txt = get_file_content(pialertPath + '/back/report_sample.txt') + + # Open html sample + sample_html = get_file_content(pialertPath + '/back/report_sample.html') + + # Open json sample and get only the payload part + sample_json_payload = json.loads(get_file_content(pialertPath + '/back/webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"] + + sample_msg = noti_struc(sample_json_payload, sample_txt, sample_html ) + + + if testType == 'Email': + send_email(sample_msg) + elif testType == 'Webhooks': + send_webhook (sample_msg) + elif testType == 'Apprise': + send_apprise (sample_msg) + elif testType == 'NTFY': + send_ntfy (sample_msg) + elif testType == 'PUSHSAFER': + send_pushsafer (sample_msg) + else: + mylog('none', ['[Test Publishers] No test matches: ', testType]) + + mylog('minimal', ['[Test Publishers] END Test: ', testType]) diff --git a/pialert/reporting.py b/pialert/reporting.py index 4b25ebfd..25d851f6 100755 --- a/pialert/reporting.py +++ b/pialert/reporting.py @@ -25,7 +25,6 @@ import const from const import pialertPath, logPath, apiPath from helper import noti_struc, generate_mac_links, removeDuplicateNewLines, timeNowTZ, hide_email, updateState, get_file_content, write_file from logger import logResult, mylog, print_log -from plugin import execute_plugin from publishers.email import (check_config as email_check_config, send as send_email ) @@ -44,7 +43,7 @@ from publishers.mqtt import (check_config as mqtt_check_config, #=============================================================================== # REPORTING #=============================================================================== -# create a json for webhook and mqtt notifications to provide further integration options +# create a json of the notifications to provide further integration options (e.g. used in webhook, mqtt notifications) json_final = [] @@ -183,21 +182,6 @@ def send_notifications (db): mylog('verbose', ['[Notification] included sections: ', conf.INCLUDED_SECTIONS ]) - # if 'internet' in conf.INCLUDED_SECTIONS : - # # Compose Internet Section - # sqlQuery = """SELECT eve_MAC as MAC, eve_IP as IP, eve_DateTime as Datetime, eve_EventType as "Event Type", eve_AdditionalInfo as "More info" FROM Events - # WHERE eve_PendingAlertEmail = 1 AND eve_MAC = 'Internet' - # ORDER BY eve_DateTime""" - - # notiStruc = construct_notifications(db, sqlQuery, "Internet IP change") - - # # collect "internet" (IP changes) for the webhook json - # json_internet = notiStruc.json["data"] - - # mail_text = mail_text.replace ('', notiStruc.text + '\n') - # mail_html = mail_html.replace ('', notiStruc.html) - # mylog('verbose', ['[Notification] Internet sections done.']) - if 'new_devices' in conf.INCLUDED_SECTIONS : # Compose New Devices Section sqlQuery = """SELECT eve_MAC as MAC, eve_DateTime as Datetime, dev_LastIP as IP, eve_EventType as "Event Type", dev_Name as "Device name", dev_Comments as Comments FROM Events_Devices @@ -223,7 +207,7 @@ def send_notifications (db): notiStruc = construct_notifications(db, sqlQuery, "Down devices") - # collect "new_devices" for the webhook json + # collect "down_devices" for the webhook json json_down_devices = notiStruc.json["data"] mail_text = mail_text.replace ('', notiStruc.text + '\n') @@ -282,7 +266,7 @@ def send_notifications (db): write_file (logPath + '/report_output.txt', mail_text) write_file (logPath + '/report_output.html', mail_html) - # Send Mail + # Notify is something to report if json_internet != [] or json_new_devices != [] or json_down_devices != [] or json_events != [] or json_ports != [] or plugins_report: mylog('none', ['[Notification] Changes detected, sending reports']) @@ -356,38 +340,14 @@ def check_config(service): if service == 'email': return email_check_config() - # if conf.SMTP_SERVER == '' or conf.REPORT_FROM == '' or conf.REPORT_TO == '': - # mylog('none', ['[Check Config] Error: Email service not set up correctly. Check your pialert.conf SMTP_*, REPORT_FROM and REPORT_TO variables.']) - # return False - # else: - # return True - if service == 'apprise': return apprise_check_config() - # if conf.APPRISE_URL == '' or conf.APPRISE_HOST == '': - # mylog('none', ['[Check Config] Error: Apprise service not set up correctly. Check your pialert.conf APPRISE_* variables.']) - # return False - # else: - # return True - if service == 'webhook': return webhook_check_config() - - # if conf.WEBHOOK_URL == '': - # mylog('none', ['[Check Config] Error: Webhook service not set up correctly. Check your pialert.conf WEBHOOK_* variables.']) - # return False - # else: - # return True if service == 'ntfy': return ntfy_check_config () - # - # if conf.NTFY_HOST == '' or conf.NTFY_TOPIC == '': - # mylog('none', ['[Check Config] Error: NTFY service not set up correctly. Check your pialert.conf NTFY_* variables.']) - # return False - # else: - # return True if service == 'pushsafer': return pushsafer_check_config() @@ -472,85 +432,3 @@ def skip_repeated_notifications (db): db.commitDB() -#=============================================================================== -# UTIL -#=============================================================================== - -#------------------------------------------------------------------------------- -def check_and_run_event(db, pluginsState): - - sql = db.sql # TO-DO - sql.execute(""" select * from Parameters where par_ID = "Front_Event" """) - rows = sql.fetchall() - - event, param = ['',''] - if len(rows) > 0 and rows[0]['par_Value'] != 'finished': - keyValue = rows[0]['par_Value'].split('|') - - if len(keyValue) == 2: - event = keyValue[0] - param = keyValue[1] - else: - return pluginsState - - if event == 'test': - handle_test(param) - if event == 'run': - pluginsState = handle_run(param, db, pluginsState) - - # clear event execution flag - sql.execute ("UPDATE Parameters SET par_Value='finished' WHERE par_ID='Front_Event'") - - # commit to DB - db.commitDB() - - mylog('debug', [f'[MAIN] processScan3: {pluginsState.processScan}']) - - return pluginsState - -#------------------------------------------------------------------------------- -def handle_run(runType, db, pluginsState): - - mylog('minimal', ['[', timeNowTZ(), '] START Run: ', runType]) - - # run the plugin to run - for plugin in conf.plugins: - if plugin["unique_prefix"] == runType: - pluginsState = execute_plugin(db, plugin, pluginsState) - - mylog('minimal', ['[', timeNowTZ(), '] END Run: ', runType]) - return pluginsState - - - -#------------------------------------------------------------------------------- -def handle_test(testType): - - mylog('minimal', ['[', timeNowTZ(), '] START Test: ', testType]) - - # Open text sample - sample_txt = get_file_content(pialertPath + '/back/report_sample.txt') - - # Open html sample - sample_html = get_file_content(pialertPath + '/back/report_sample.html') - - # Open json sample and get only the payload part - sample_json_payload = json.loads(get_file_content(pialertPath + '/back/webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"] - - sample_msg = noti_struc(sample_json_payload, sample_txt, sample_html ) - - - if testType == 'Email': - send_email(sample_msg) - elif testType == 'Webhooks': - send_webhook (sample_msg) - elif testType == 'Apprise': - send_apprise (sample_msg) - elif testType == 'NTFY': - send_ntfy (sample_msg) - elif testType == 'PUSHSAFER': - send_pushsafer (sample_msg) - else: - mylog('none', ['[Test Publishers] No test matches: ', testType]) - - mylog('minimal', ['[Test Publishers] END Test: ', testType]) diff --git a/pialert/scheduler.py b/pialert/scheduler.py index ff2685ff..dbd94b7c 100755 --- a/pialert/scheduler.py +++ b/pialert/scheduler.py @@ -25,9 +25,7 @@ class schedule_class: nowTime = datetime.datetime.now(conf.tz).replace(microsecond=0) # Run the schedule if the current time is past the schedule time we saved last time and - # (maybe the following check is unnecessary:) - # if the last run is past the last time we run a scheduled Pholus scan - # if nowTime > self.last_next_schedule and self.last_run < self.last_next_schedule: + # (maybe the following check is unnecessary) if nowTime > self.last_next_schedule: mylog('debug',f'[Scheduler] - Scheduler run for {self.service}: YES') self.was_last_schedule_used = True