mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-14 22:21:38 -07:00
Support for mapping plun obj to DB table
This commit is contained in:
18
README.md
18
README.md
@@ -7,7 +7,6 @@ Scans for devices connected to your WIFI / LAN and alerts you if new and unknown
|
|||||||
|
|
||||||
![Main screen][main]
|
![Main screen][main]
|
||||||
|
|
||||||
|
|
||||||
# 🐳 Docker image
|
# 🐳 Docker image
|
||||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
|
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
|
||||||
[](https://github.com/jokob-sk/Pi.Alert)
|
[](https://github.com/jokob-sk/Pi.Alert)
|
||||||
@@ -30,7 +29,6 @@ The system continuously scans the network for, **New devices**, **New connection
|
|||||||
examines the DHCP leases (addresses assigned) to find active devices
|
examines the DHCP leases (addresses assigned) to find active devices
|
||||||
that were not discovered by the other methods.
|
that were not discovered by the other methods.
|
||||||
|
|
||||||
|
|
||||||
## 🧩 Integrations
|
## 🧩 Integrations
|
||||||
- [Apprise](https://hub.docker.com/r/caronc/apprise), [Pushsafer](https://www.pushsafer.com/), [NTFY](https://ntfy.sh/)
|
- [Apprise](https://hub.docker.com/r/caronc/apprise), [Pushsafer](https://www.pushsafer.com/), [NTFY](https://ntfy.sh/)
|
||||||
- [Webhooks](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md) ([sample JSON](docs/webhook_json_sample.json))
|
- [Webhooks](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md) ([sample JSON](docs/webhook_json_sample.json))
|
||||||
@@ -49,18 +47,16 @@ The system continuously scans the network for, **New devices**, **New connection
|
|||||||
- Sessions, Connected devices, Favorites, Events, Presence, Concurrent devices, Down alerts, IP's
|
- Sessions, Connected devices, Favorites, Events, Presence, Concurrent devices, Down alerts, IP's
|
||||||
- Manual Nmap scans, Optional speedtest for Device "Internet"
|
- Manual Nmap scans, Optional speedtest for Device "Internet"
|
||||||
- Simple Network relationship display
|
- Simple Network relationship display
|
||||||
- Maintenance tasks and Settings like:
|
- Maintenance tasks and Settings like:
|
||||||
- Status Infos (active scans, database size, backup counter)
|
- Theme Selection (blue, red, green, yellow, black, purple) and Light/Dark-Mode Switch
|
||||||
- Theme Selection (blue, red, green, yellow, black, purple) and Light/Dark-Mode Switch
|
|
||||||
- Language Selection (English, German, Spanish)
|
|
||||||
- Pause arp-scan
|
|
||||||
- DB maintenance, Backup, Restore tools and CSV Export / Import
|
- DB maintenance, Backup, Restore tools and CSV Export / Import
|
||||||
- Configurable login to prevent unauthorized use.
|
- Simple login Support
|
||||||
- 🌟(Experimental) [Plugin system](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins)
|
- 🌟(Experimental) [Plugin system](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins)
|
||||||
- Create custom plugins with automatically generated settings and UI.
|
- Create custom plugins with automatically generated settings and UI.
|
||||||
- Monitor anything for changes
|
- Monitor anything for changes
|
||||||
- Check the instructions carefully if you are up for a challenge!
|
- Check the instructions carefully if you are up for a challenge! Current plugins include:
|
||||||
- Help/FAQ Section
|
- Detecting Rogue DHCP servers
|
||||||
|
- Monitoring HTTP status changes of domains/URLs
|
||||||
|
|
||||||
| ![Screen 1][screen1] | ![Screen 2][screen2] | ![Screen 5][screen5] |
|
| ![Screen 1][screen1] | ![Screen 2][screen2] | ![Screen 5][screen5] |
|
||||||
|----------------------|----------------------| ----------------------|
|
|----------------------|----------------------| ----------------------|
|
||||||
@@ -93,8 +89,6 @@ Device Management [instructions](docs/DEVICE_MANAGEMENT.md) | Old Versions [Hist
|
|||||||
|
|
||||||
## ☕ Support me
|
## ☕ Support me
|
||||||
|
|
||||||
Disclaimer: Please only donate if you don't have any debt yourself. Support yourself first, then others.
|
|
||||||
|
|
||||||
<a href="https://github.com/sponsors/jokob-sk" target="_blank"><img src="https://i.imgur.com/X6p5ACK.png" alt="Sponsor Me on GitHub" style="height: 30px !important;width: 117px !important;" width="150px" ></a>
|
<a href="https://github.com/sponsors/jokob-sk" target="_blank"><img src="https://i.imgur.com/X6p5ACK.png" alt="Sponsor Me on GitHub" style="height: 30px !important;width: 117px !important;" width="150px" ></a>
|
||||||
<a href="https://www.buymeacoffee.com/jokobsk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 117px !important;" width="117px" height="30px" ></a>
|
<a href="https://www.buymeacoffee.com/jokobsk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 117px !important;" width="117px" height="30px" ></a>
|
||||||
<a href="https://www.patreon.com/user?u=84385063" target="_blank"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" alt="Support me on patreon" style="height: 30px !important;width: 117px !important;" width="117px" ></a>
|
<a href="https://www.patreon.com/user?u=84385063" target="_blank"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" alt="Support me on patreon" style="height: 30px !important;width: 117px !important;" width="117px" ></a>
|
||||||
|
|||||||
@@ -1197,8 +1197,6 @@ def copy_pihole_network ():
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
def read_DHCP_leases ():
|
def read_DHCP_leases ():
|
||||||
reporting = False
|
|
||||||
|
|
||||||
# Read DHCP Leases
|
# Read DHCP Leases
|
||||||
# Bugfix #1 - dhcp.leases: lines with different number of columns (5 col)
|
# Bugfix #1 - dhcp.leases: lines with different number of columns (5 col)
|
||||||
data = []
|
data = []
|
||||||
@@ -1209,14 +1207,13 @@ def read_DHCP_leases ():
|
|||||||
if len(row) == 5 :
|
if len(row) == 5 :
|
||||||
data.append (row)
|
data.append (row)
|
||||||
|
|
||||||
# Insert into PiAlert table
|
# Insert into PiAlert table
|
||||||
sql.execute ("DELETE FROM DHCP_Leases")
|
|
||||||
sql.executemany ("""INSERT INTO DHCP_Leases (DHCP_DateTime, DHCP_MAC,
|
sql.executemany ("""INSERT INTO DHCP_Leases (DHCP_DateTime, DHCP_MAC,
|
||||||
DHCP_IP, DHCP_Name, DHCP_MAC2)
|
DHCP_IP, DHCP_Name, DHCP_MAC2)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
""", data)
|
""", data)
|
||||||
|
|
||||||
return reporting
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
def save_scanned_devices (p_arpscan_devices, p_cycle_interval):
|
def save_scanned_devices (p_arpscan_devices, p_cycle_interval):
|
||||||
@@ -1591,8 +1588,7 @@ def update_devices_data_from_scan ():
|
|||||||
sql.execute ("""UPDATE Devices
|
sql.execute ("""UPDATE Devices
|
||||||
SET dev_NAME = (SELECT PH_Name FROM PiHole_Network
|
SET dev_NAME = (SELECT PH_Name FROM PiHole_Network
|
||||||
WHERE PH_MAC = dev_MAC)
|
WHERE PH_MAC = dev_MAC)
|
||||||
WHERE (dev_Name = "(unknown)"
|
WHERE (dev_Name in ("(unknown)", "(name not found)", "" )
|
||||||
OR dev_Name = ""
|
|
||||||
OR dev_Name IS NULL)
|
OR dev_Name IS NULL)
|
||||||
AND EXISTS (SELECT 1 FROM PiHole_Network
|
AND EXISTS (SELECT 1 FROM PiHole_Network
|
||||||
WHERE PH_MAC = dev_MAC
|
WHERE PH_MAC = dev_MAC
|
||||||
@@ -1603,8 +1599,7 @@ def update_devices_data_from_scan ():
|
|||||||
sql.execute ("""UPDATE Devices
|
sql.execute ("""UPDATE Devices
|
||||||
SET dev_NAME = (SELECT DHCP_Name FROM DHCP_Leases
|
SET dev_NAME = (SELECT DHCP_Name FROM DHCP_Leases
|
||||||
WHERE DHCP_MAC = dev_MAC)
|
WHERE DHCP_MAC = dev_MAC)
|
||||||
WHERE (dev_Name = "(unknown)"
|
WHERE (dev_Name in ("(unknown)", "(name not found)", "" )
|
||||||
OR dev_Name = ""
|
|
||||||
OR dev_Name IS NULL)
|
OR dev_Name IS NULL)
|
||||||
AND EXISTS (SELECT 1 FROM DHCP_Leases
|
AND EXISTS (SELECT 1 FROM DHCP_Leases
|
||||||
WHERE DHCP_MAC = dev_MAC)""")
|
WHERE DHCP_MAC = dev_MAC)""")
|
||||||
@@ -1625,6 +1620,8 @@ def update_devices_data_from_scan ():
|
|||||||
sql.executemany ("UPDATE Devices SET dev_Vendor = ? WHERE dev_MAC = ? ",
|
sql.executemany ("UPDATE Devices SET dev_Vendor = ? WHERE dev_MAC = ? ",
|
||||||
recordsToUpdate )
|
recordsToUpdate )
|
||||||
|
|
||||||
|
# clean-up device leases table
|
||||||
|
sql.execute ("DELETE FROM DHCP_Leases")
|
||||||
print_log ('Update devices end')
|
print_log ('Update devices end')
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@@ -2353,15 +2350,7 @@ def send_notifications ():
|
|||||||
mail_text = mail_text.replace ('<PORTS_TABLE>', portsTxt )
|
mail_text = mail_text.replace ('<PORTS_TABLE>', portsTxt )
|
||||||
|
|
||||||
if 'plugins' in INCLUDED_SECTIONS and ENABLE_PLUGINS:
|
if 'plugins' in INCLUDED_SECTIONS and ENABLE_PLUGINS:
|
||||||
# Compose Plugins Section
|
# Compose Plugins Section
|
||||||
# sqlQuery = get_plugin_events_to_report_on_SQL()
|
|
||||||
|
|
||||||
# # handle plugins
|
|
||||||
# for plugin in plugins:
|
|
||||||
# print_plugin_info(plugin, ['display_name','description'])
|
|
||||||
|
|
||||||
# pref = plugin["unique_prefix"]
|
|
||||||
|
|
||||||
sqlQuery = """SELECT Plugin, Object_PrimaryId, Object_SecondaryId, DateTimeChanged, Watched_Value1, Watched_Value2, Watched_Value3, Watched_Value4, Status from Plugins_Events"""
|
sqlQuery = """SELECT Plugin, Object_PrimaryId, Object_SecondaryId, DateTimeChanged, Watched_Value1, Watched_Value2, Watched_Value3, Watched_Value4, Status from Plugins_Events"""
|
||||||
|
|
||||||
notiStruc = construct_notifications(sqlQuery, "Plugins")
|
notiStruc = construct_notifications(sqlQuery, "Plugins")
|
||||||
@@ -3994,7 +3983,7 @@ def process_plugin_events(plugin):
|
|||||||
pluginEvents[index].status = "watched-not-changed"
|
pluginEvents[index].status = "watched-not-changed"
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
# Merge existing plugin objects with newly discovered ones and update existin ones with new values
|
# Merge existing plugin objects with newly discovered ones and update existing ones with new values
|
||||||
for eveObj in pluginEvents:
|
for eveObj in pluginEvents:
|
||||||
if eveObj.status == 'new':
|
if eveObj.status == 'new':
|
||||||
pluginObjects.append(eveObj)
|
pluginObjects.append(eveObj)
|
||||||
@@ -4037,7 +4026,74 @@ def process_plugin_events(plugin):
|
|||||||
# insert only events if they are to be reported on
|
# insert only events if they are to be reported on
|
||||||
if plugObj.status in get_plugin_setting_value(plugin, "REPORT_ON"):
|
if plugObj.status in get_plugin_setting_value(plugin, "REPORT_ON"):
|
||||||
|
|
||||||
sql.execute ("INSERT INTO Plugins_Events (Plugin, Object_PrimaryID, Object_SecondaryID, DateTimeCreated, DateTimeChanged, Watched_Value1, Watched_Value2, Watched_Value3, Watched_Value4, Status, Extra, UserData, ForeignKey) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", (plugObj.pluginPref, plugObj.primaryId , plugObj.secondaryId , createdTime, plugObj.changed , plugObj.watched1 , plugObj.watched2 , plugObj.watched3 , plugObj.watched4 , plugObj.status , plugObj.extra, plugObj.userData, plugObj.foreignKey ))
|
sql.execute ("INSERT INTO Plugins_Events (Plugin, Object_PrimaryID, Object_SecondaryID, DateTimeCreated, DateTimeChanged, Watched_Value1, Watched_Value2, Watched_Value3, Watched_Value4, Status, Extra, UserData, ForeignKey) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", (plugObj.pluginPref, plugObj.primaryId , plugObj.secondaryId , createdTime, plugObj.changed , plugObj.watched1 , plugObj.watched2 , plugObj.watched3 , plugObj.watched4 , plugObj.status , plugObj.extra, plugObj.userData, plugObj.foreignKey ))
|
||||||
|
|
||||||
|
# Perform databse table mapping if enabled for the plugin
|
||||||
|
# "mapped_to_table": "DHCP_Leases",
|
||||||
|
|
||||||
|
if len(pluginEvents) > 0 and "mapped_to_table" in plugin:
|
||||||
|
|
||||||
|
sqlParams = []
|
||||||
|
|
||||||
|
dbTable = plugin['mapped_to_table']
|
||||||
|
|
||||||
|
mylog('debug', [' [Plugins] Mapping objects to database table: ', dbTable])
|
||||||
|
|
||||||
|
# collect all columns to be mapped
|
||||||
|
mappedCols = []
|
||||||
|
columnsStr = ''
|
||||||
|
valuesStr = ''
|
||||||
|
|
||||||
|
for clmn in plugin['database_column_definitions']:
|
||||||
|
if 'mapped_to_column' in clmn:
|
||||||
|
mappedCols.append(clmn)
|
||||||
|
columnsStr = f'{columnsStr}, "{clmn["mapped_to_column"]}"'
|
||||||
|
valuesStr = f'{valuesStr}, ?'
|
||||||
|
|
||||||
|
if len(columnsStr) > 0:
|
||||||
|
columnsStr = columnsStr[1:] # remove first ','
|
||||||
|
valuesStr = valuesStr[1:] # remove first ','
|
||||||
|
|
||||||
|
# map the column names to plugin object event values
|
||||||
|
for plgEv in pluginEvents:
|
||||||
|
|
||||||
|
tmpList = []
|
||||||
|
|
||||||
|
for col in mappedCols:
|
||||||
|
if col['column'] == 'Index':
|
||||||
|
tmpList.append(plgEv.index)
|
||||||
|
elif col['column'] == 'Plugin':
|
||||||
|
tmpList.append(plgEv.pluginPref)
|
||||||
|
elif col['column'] == 'Object_PrimaryID':
|
||||||
|
tmpList.append(plgEv.primaryId)
|
||||||
|
elif col['column'] == 'Object_SecondaryID':
|
||||||
|
tmpList.append(plgEv.secondaryId)
|
||||||
|
elif col['column'] == 'DateTimeCreated':
|
||||||
|
tmpList.append(plgEv.created)
|
||||||
|
elif col['column'] == 'DateTimeChanged':
|
||||||
|
tmpList.append(plgEv.changed)
|
||||||
|
elif col['column'] == 'Watched_Value1':
|
||||||
|
tmpList.append(plgEv.watched1)
|
||||||
|
elif col['column'] == 'Watched_Value2':
|
||||||
|
tmpList.append(plgEv.watched2)
|
||||||
|
elif col['column'] == 'Watched_Value3':
|
||||||
|
tmpList.append(plgEv.watched3)
|
||||||
|
elif col['column'] == 'Watched_Value4':
|
||||||
|
tmpList.append(plgEv.watched4)
|
||||||
|
elif col['column'] == 'UserData':
|
||||||
|
tmpList.append(plgEv.userData)
|
||||||
|
elif col['column'] == 'Extra':
|
||||||
|
tmpList.append(plgEv.extra)
|
||||||
|
elif col['column'] == 'Status':
|
||||||
|
tmpList.append(plgEv.status)
|
||||||
|
|
||||||
|
sqlParams.append(tuple(tmpList))
|
||||||
|
|
||||||
|
q = f'INSERT into {dbTable} ({columnsStr}) VALUES ({valuesStr})'
|
||||||
|
|
||||||
|
mylog('debug', [' [Plugins] SQL query for mapping: ', q ])
|
||||||
|
|
||||||
|
sql.executemany (q, sqlParams)
|
||||||
|
|
||||||
commitDB()
|
commitDB()
|
||||||
|
|
||||||
@@ -4084,7 +4140,7 @@ class plugin_object_class:
|
|||||||
|
|
||||||
self.watchedHash = str(hash(tmp))
|
self.watchedHash = str(hash(tmp))
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Combine plugin objects, keep user-defined values, created time, changed time if nothing changed and the index
|
# Combine plugin objects, keep user-defined values, created time, changed time if nothing changed and the index
|
||||||
def combine_plugin_objects(old, new):
|
def combine_plugin_objects(old, new):
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ services:
|
|||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
|
- ${APP_DATA_LOCATION}/pialert2/config:/home/pi/pialert/config
|
||||||
# - ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
# - ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
||||||
- ${APP_DATA_LOCATION}/pialert/db:/home/pi/pialert/db
|
- ${APP_DATA_LOCATION}/pialert2/db:/home/pi/pialert/db
|
||||||
# (optional) useful for debugging if you have issues setting up the container
|
# (optional) useful for debugging if you have issues setting up the container
|
||||||
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
||||||
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
|
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"data_source": "python-script",
|
"data_source": "python-script",
|
||||||
"localized": ["display_name", "description", "icon"],
|
"localized": ["display_name", "description", "icon"],
|
||||||
|
"mapped_to_table": "DHCP_Leases",
|
||||||
"display_name" : [{
|
"display_name" : [{
|
||||||
"language_code":"en_us",
|
"language_code":"en_us",
|
||||||
"string" : "DHCP Leases"
|
"string" : "DHCP Leases"
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"database_column_definitions":
|
"database_column_definitions":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"column": "Index",
|
"column": "Index",
|
||||||
"css_classes": "col-sm-2",
|
"css_classes": "col-sm-2",
|
||||||
"show": false,
|
"show": false,
|
||||||
"type": "label",
|
"type": "label",
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"column": "Object_PrimaryID",
|
"column": "Object_PrimaryID",
|
||||||
|
"mapped_to_column": "DHCP_MAC",
|
||||||
"css_classes": "col-sm-2",
|
"css_classes": "col-sm-2",
|
||||||
"show": true,
|
"show": true,
|
||||||
"type": "devicemac",
|
"type": "devicemac",
|
||||||
@@ -60,11 +62,12 @@
|
|||||||
"localized": ["name"],
|
"localized": ["name"],
|
||||||
"name":[{
|
"name":[{
|
||||||
"language_code":"en_us",
|
"language_code":"en_us",
|
||||||
"string" : "IP"
|
"string" : "MAC address"
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"column": "Object_SecondaryID",
|
"column": "Object_SecondaryID",
|
||||||
|
"mapped_to_column": "DHCP_IP",
|
||||||
"css_classes": "col-sm-2",
|
"css_classes": "col-sm-2",
|
||||||
"show": true,
|
"show": true,
|
||||||
"type": "deviceip",
|
"type": "deviceip",
|
||||||
@@ -73,7 +76,7 @@
|
|||||||
"localized": ["name"],
|
"localized": ["name"],
|
||||||
"name":[{
|
"name":[{
|
||||||
"language_code":"en_us",
|
"language_code":"en_us",
|
||||||
"string" : "MAC address"
|
"string" : "IP"
|
||||||
}]
|
}]
|
||||||
} ,
|
} ,
|
||||||
{
|
{
|
||||||
@@ -91,6 +94,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"column": "DateTimeChanged",
|
"column": "DateTimeChanged",
|
||||||
|
"mapped_to_column": "DHCP_DateTime",
|
||||||
"css_classes": "col-sm-2",
|
"css_classes": "col-sm-2",
|
||||||
"show": true,
|
"show": true,
|
||||||
"type": "label",
|
"type": "label",
|
||||||
@@ -117,6 +121,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"column": "Watched_Value2",
|
"column": "Watched_Value2",
|
||||||
|
"mapped_to_column": "DHCP_Name",
|
||||||
"css_classes": "col-sm-2",
|
"css_classes": "col-sm-2",
|
||||||
"show": true,
|
"show": true,
|
||||||
"type": "label",
|
"type": "label",
|
||||||
|
|||||||
Reference in New Issue
Block a user