Compare commits

...

197 Commits

Author SHA1 Message Date
jokob-sk
e1f9ca05b7 wf docs 2025-04-01 08:20:00 +11:00
Максим Горпиніч
4aaf86f0fc Translated using Weblate (Ukrainian)
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (743 of 743 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-03-31 13:27:45 +02:00
jokob-sk
9bb21ad303 wf docs 2025-03-31 18:46:55 +11:00
jokob-sk
e1197eb3f8 wf work + docs 2025-03-31 18:05:15 +11:00
jokob-sk
2c445ccaeb wf work + docs 2025-03-31 18:04:56 +11:00
jokob-sk
8a07f7067b Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-31 08:12:57 +11:00
jokob-sk
d86c2a5023 Move ObjectGUID to the end 2025-03-31 08:12:32 +11:00
Максим Горпиніч
2b51674e52 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (737 of 737 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-03-30 19:39:24 +02:00
Sylvain Pichon
eb6820dd93 Translated using Weblate (French)
Currently translated at 100.0% (737 of 737 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-03-30 19:39:24 +02:00
Ettore Atalan
b156246cb0 Translated using Weblate (German)
Currently translated at 89.2% (658 of 737 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-03-30 19:39:24 +02:00
Hosted Weblate
716c6a4046 Merge branch 'origin/main' into Weblate.
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-30 08:30:09 +02:00
Massimo Pissarello
114b5a2621 Translated using Weblate (Italian)
Currently translated at 100.0% (737 of 737 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-03-30 08:30:09 +02:00
jokob-sk
02b19c833e Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-03-30 17:29:56 +11:00
jokob-sk
e0c06548ba wf work + fa upgrade + css cleanup + network tweaks 2025-03-30 17:29:22 +11:00
Anonymous
4d401f60dc Translated using Weblate (Portuguese (Brazil))
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 59.5% (439 of 737 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-03-30 07:23:31 +02:00
Hosted Weblate
391be9a49d Merge branch 'origin/main' into Weblate. 2025-03-29 23:25:54 +00:00
Sylvain Pichon
587fb6036c Translated using Weblate (French)
Currently translated at 100.0% (719 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-03-29 23:25:52 +00:00
jokob-sk
2d4ca7e8ae Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-03-30 10:25:29 +11:00
jokob-sk
3f74173245 wf work 2025-03-30 10:25:03 +11:00
Максим Горпиніч
e35a3578dd Translated using Weblate (Ukrainian)
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (719 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-03-29 08:51:03 +01:00
Максим Горпиніч
e957453d33 Translated using Weblate (Ukrainian)
Currently translated at 99.7% (717 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-03-29 07:58:04 +01:00
Anonymous
3c31a85a68 Translated using Weblate (Catalan)
Currently translated at 99.5% (716 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-03-29 07:58:03 +01:00
Anonymous
7054c44976 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 86.7% (624 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-03-29 07:58:03 +01:00
Anonymous
0110675806 Translated using Weblate (Polish)
Currently translated at 86.9% (625 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-03-29 07:58:03 +01:00
Anonymous
a4ecd7f571 Translated using Weblate (Portuguese (Brazil))
Currently translated at 61.7% (444 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-03-29 07:58:03 +01:00
Anonymous
b671abd93f Translated using Weblate (Italian)
Currently translated at 99.5% (716 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-03-29 07:58:03 +01:00
Anonymous
67db3c1582 Translated using Weblate (Russian)
Currently translated at 99.5% (716 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-03-29 07:58:02 +01:00
Anonymous
f25d6c18e5 Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.5% (622 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-03-29 07:58:02 +01:00
Anonymous
e5f7698461 Translated using Weblate (French)
Currently translated at 99.5% (716 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-03-29 07:58:02 +01:00
Anonymous
371e996a25 Translated using Weblate (Spanish)
Currently translated at 95.8% (689 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-03-29 07:58:01 +01:00
Anonymous
20342ed0b5 Translated using Weblate (German)
Currently translated at 89.7% (645 of 719 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-03-29 07:58:01 +01:00
jokob-sk
5d01af1758 wf work 2025-03-29 17:21:29 +11:00
jokob-sk
a0561b2016 wf work 2025-03-29 17:03:59 +11:00
jokob-sk
f2e218230e SQL query fix
Some checks are pending
URL Path Check / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-29 12:55:24 +11:00
Jokob @NetAlertX
e25c471626 Merge pull request #1029 from jokob-sk/next_release
Next release - Workflow work
2025-03-29 12:47:56 +11:00
jokob-sk
76419db0e3 wf work 2025-03-29 12:46:27 +11:00
jokob-sk
929964f9e2 wf work 2025-03-29 12:31:29 +11:00
jokob-sk
7e5373b2cd wf work 2025-03-27 21:23:11 +11:00
jokob-sk
3b869f5365 stop devParentMAC overwrite if specified #1021
Some checks failed
URL Path Check / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-03-23 15:24:47 +11:00
jokob-sk
e996c9eccc stop devParentMAC overwrite if specified #1021 2025-03-23 15:24:01 +11:00
jokob-sk
393904c91f stop devParentMAC overwrite if specified #1021 2025-03-23 15:12:07 +11:00
jokob-sk
8d9a4d23d1 stop devParentMAC overwrite if specified #1021 2025-03-23 13:23:39 +11:00
jokob-sk
4092452363 wf work 2025-03-22 19:17:52 +11:00
jokob-sk
2b61665ee8 github actions
Some checks failed
URL Path Check / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-03-22 10:48:58 +11:00
jokob-sk
6c28926e39 incorrect starter app.conf LOADED_PLUGINS #1023 2025-03-22 10:47:12 +11:00
jokob-sk
af4beb9f58 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-03-22 10:33:02 +11:00
jokob-sk
e55c561e55 ICMP quotes #1025 2025-03-22 10:32:32 +11:00
jokob-sk
0d4185731c wf work 2025-03-22 10:30:26 +11:00
Jokob @NetAlertX
0b6de5545b Merge pull request #1024 from cvc90/cvc90-update-front-userNotifications-urls
Changing absolute path URL to relative path URL in userNotifications.php
2025-03-22 08:48:20 +11:00
Carlos V.
9d04f943bc Update userNotifications.php
Updated “absolute” URLs to “relative” URLs for correct operation through proxys.
2025-03-21 19:01:42 +01:00
jokob-sk
038a6a63eb wf work 2025-03-21 06:29:31 +11:00
Jokob @NetAlertX
6f8b2f5071 Merge pull request #1022 from cvc90/cvc90-update-front-devices-urls
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Changing absolute path URL to relative path URL in devices.php
2025-03-21 06:24:12 +11:00
Carlos V.
fd9695c743 Update devices.php
Updated “absolute” URLs to “relative” URLs for correct operation through proxys.
2025-03-20 17:14:40 +01:00
jokob-sk
ba300f7023 stop devParentMAC overwrite if specified #1021
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-20 11:12:29 +11:00
jokob-sk
92fce6f14a wf work 2025-03-20 11:02:54 +11:00
jokob-sk
fe722a5caa MQTT #1019
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-03-18 06:36:18 +11:00
jokob-sk
0512ddd143 wf work 2025-03-18 06:32:44 +11:00
jokob-sk
1aaa22c178 OPENWRT/LUCI #1010
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-03-16 07:54:03 +11:00
jokob-sk
1efdf66c19 wf work 2025-03-15 13:19:58 +11:00
jokob-sk
60a1349be5 OPENWRT/LUCI #1010
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-15 08:52:46 +11:00
jokob-sk
b99f949363 MQTT #1019 2025-03-15 08:13:14 +11:00
jokob-sk
9b340532be wf work 2025-03-15 07:56:16 +11:00
jokob-sk
7d6855053e wf work 2025-03-14 07:58:29 +11:00
jokob-sk
432a4d9d69 Initial commit on next_release branch 2025-03-10 07:42:44 +11:00
Jokob @NetAlertX
8de6749ce3 Update docker_dev.yml
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-03-10 07:38:52 +11:00
GoldBull3t
95345518a1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 62.0% (445 of 717 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-03-02 17:08:53 +01:00
jokob-sk
f5713d4178 Chore:FAQ removal 2025-03-01 11:40:55 +11:00
jokob-sk
6f8fb21787 docs, GH Actions 2025-03-01 11:01:15 +11:00
jokob-sk
4b0c7f2c01 docs, MQTT, GH Actions 2025-03-01 10:06:32 +11:00
jokob-sk
bf3d497d26 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-03-01 09:44:15 +11:00
jokob-sk
47d9a9300e docs, MQTT, GH Actions 2025-03-01 09:44:11 +11:00
Jokob @NetAlertX
fd107fe4f7 Merge pull request #1008 from xfilo/main
OMDSDNOPENAPI - Refactored data collection into a class, improved code clarity with comments
2025-02-25 06:59:32 +11:00
xfilo
9513a5a2ae Merge branch 'jokob-sk:main' into main 2025-02-24 20:51:53 +01:00
xfilo
bf151bd69a OMDSDNOPENAPI - Refactored data collection into a class, improved code clarity with comments 2025-02-24 20:51:01 +01:00
Jokob @NetAlertX
3a312fd5ed Merge pull request #1007 from xfilo/main
OMDSDNOPENAPI - Fixed example in README.md, improved logging and code logic
2025-02-25 06:13:06 +11:00
xfilo
03bf4f4050 Merge branch 'main' of https://github.com/xfilo/NetAlertX 2025-02-24 16:03:18 +01:00
xfilo
bf3fdd2766 OMDSDNOPENAPI - Rephrased error messages, improved logging and code logic 2025-02-24 16:03:07 +01:00
xfilo
befb2574e9 Merge branch 'jokob-sk:main' into main 2025-02-24 11:38:35 +01:00
xfilo
52de3ae872 OMDSDNOPENAPI - Updated example image in README.md 2025-02-24 11:36:55 +01:00
Jokob @NetAlertX
9be9728cd6 Merge pull request #1006 from xfilo/main
OMDSDNOPENAPI - Run command change due to plugin folder rename
2025-02-24 20:57:05 +11:00
xfilo
65a5d35801 OMDSDNOPENAPI - Run command change due to plugin folder rename 2025-02-24 10:52:18 +01:00
jokob-sk
1e714005a5 docs 2025-02-24 14:34:26 +11:00
jokob-sk
2a25f38268 OMDSDNOPENAPI cleanup + opensense script 2025-02-24 12:52:12 +11:00
Jokob @NetAlertX
65a0f90bd8 Merge pull request #1005 from xfilo/main
New plugin: Omada SDN import using OpenAPI (OMDSDNOPENAPI) by @xfilo 🙏
2025-02-24 12:19:06 +11:00
xfilo
4d77ff3ff1 New plugin for Omada SDN import using OpenAPI 2025-02-24 00:51:44 +01:00
jokob-sk
500129c440 removal of default dropdown values on device 2025-02-24 10:13:48 +11:00
jokob-sk
a320b2910f docs 2025-02-23 07:41:35 +11:00
jokob-sk
ac7e278a36 docs 2025-02-22 13:19:32 +11:00
jokob-sk
04ab1d1fb3 docs 2025-02-22 12:56:15 +11:00
jokob-sk
268ce870a3 docs 2025-02-22 12:48:25 +11:00
jokob-sk
cda1d8b877 docs 2025-02-22 12:22:02 +11:00
jokob-sk
a68aa0bc57 docs 2025-02-22 12:17:00 +11:00
jokob-sk
7f2a1740cc docs 2025-02-22 09:56:36 +11:00
jokob-sk
3ba5c70045 docs 2025-02-22 09:54:43 +11:00
jokob-sk
fec18daab4 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-02-22 07:52:04 +11:00
jokob-sk
b71037a129 device_tracker MQTT Attributes 2025-02-22 07:51:50 +11:00
Safeguard
4f4ca0cfcb Translated using Weblate (Russian)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-02-21 13:02:04 +01:00
anton garcias
adc761a3df Translated using Weblate (Catalan)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-02-20 04:02:33 +01:00
jokob-sk
458577e071 mqtt and newdev name regex 2025-02-20 07:57:28 +11:00
jokob-sk
9d4eafea42 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-02-20 06:38:43 +11:00
jokob-sk
ac8f48c78e ASUS DHCPLSS guide 2025-02-20 06:37:50 +11:00
Patrick Seidel
2000a4291b Translated using Weblate (German)
Currently translated at 90.4% (682 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-02-18 22:42:54 +01:00
jokob-sk
97389b988f sync node in MQTT 2025-02-19 08:05:36 +11:00
jokob-sk
daba38ee0a OMADA #997
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-02-17 13:57:43 +11:00
jokob-sk
03b110950b NTFY token support 2025-02-17 09:03:34 +11:00
jokob-sk
7d9e84668c docs 2025-02-17 08:05:51 +11:00
Jokob @NetAlertX
e37acba4c4 Update DOCKER_COMPOSE.md 2025-02-17 07:09:49 +11:00
Jokob @NetAlertX
3f00c7fc40 Merge pull request #996 from Peter-Maguire/patch-1
Fix spelling mistake in unifi plugin
2025-02-17 07:05:05 +11:00
Peter Maguire
c687128f68 Fix spelling mistake 2025-02-16 12:33:29 +00:00
jokob-sk
8542d51dcf docs
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-02-16 13:19:36 +11:00
jokob-sk
c02e725b04 single quote to apostrophe replacement ’ #995 2025-02-16 10:19:24 +11:00
jokob-sk
a0e117f92e modal loop prevention #992 2025-02-16 10:06:34 +11:00
jokob-sk
ffa0457342 docs 2025-02-16 09:54:10 +11:00
jokob-sk
838352388f arpscan readme #867
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-02-15 09:34:01 +11:00
jokob-sk
dd01bebadd Omada readme #989
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-02-12 08:14:11 +11:00
jokob-sk
bdf6e62ea6 MKDocs
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-02-10 17:26:03 +11:00
jokob-sk
eb693bfdb2 MKDocs 2025-02-10 17:22:28 +11:00
jokob-sk
cc5c4a6f06 MKDocs 2025-02-10 16:53:06 +11:00
Jokob @NetAlertX
ba27769fbd Update README.md
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-02-09 12:35:26 +11:00
jokob-sk
b6c6579cb5 MKDocs 2025-02-09 12:26:57 +11:00
jokob-sk
c6adaf99f4 MKDocs 2025-02-09 12:01:02 +11:00
jokob-sk
f793dec6c5 MKDocs 2025-02-09 11:05:52 +11:00
Jokob @NetAlertX
e840320e19 Update setup-help.yml 2025-02-09 11:02:16 +11:00
jokob-sk
0fe903e076 MKDocs 2025-02-09 10:57:02 +11:00
jokob-sk
cd8124a912 MKDocs
Some checks are pending
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-02-09 08:31:54 +11:00
jokob-sk
7867700856 MKDocs 2025-02-09 07:59:26 +11:00
jokob-sk
3be39f6508 MKDocs 2025-02-09 07:50:34 +11:00
jokob-sk
b69b76aa9f Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-02-09 07:46:16 +11:00
jokob-sk
8b7431eae9 MKDocs 2025-02-09 07:46:11 +11:00
Максим Горпиніч
079a1b3954 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-02-08 19:23:07 +01:00
Massimo Pissarello
ef8bfbb59e Translated using Weblate (Italian)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-02-08 19:23:07 +01:00
Sylvain Pichon
c30d98dd77 Translated using Weblate (French)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-02-08 19:23:07 +01:00
jokob-sk
57ccdf0b0c Fix social workflow 2025-02-08 11:58:02 +11:00
Hosted Weblate
703ba5c75b Merge branch 'origin/main' into Weblate.
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-02-08 00:54:10 +01:00
Anonymous
aad74451ef Translated using Weblate (Polish)
Currently translated at 88.0% (663 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-02-08 00:54:08 +01:00
Anonymous
a787510963 Translated using Weblate (Portuguese (Brazil))
Currently translated at 32.9% (248 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-02-08 00:54:07 +01:00
jokob-sk
dd2b872712 Cron Schedule validation 2025-02-08 10:53:43 +11:00
jokob-sk
2a5e419034 Better dummy newdev MAC check 2025-02-08 08:17:37 +11:00
jokob-sk
b921144dbb treeviz flatdata experiment + better invalid TZ handling
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-02-08 08:01:05 +11:00
jokob-sk
4f2ddccdde Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-02-08 08:00:05 +11:00
jokob-sk
780b818815 treeviz flatdata experiment + better invalid TZ handling 2025-02-08 07:59:55 +11:00
jokob-sk
5779fd34c5 treeviz flatdata experiment + better invalid TZ handling 2025-02-08 07:52:13 +11:00
Safeguard
b7a6fe9112 Translated using Weblate (Russian)
Some checks are pending
docker / docker_dev (push) Waiting to run
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-02-07 00:52:35 +01:00
Максим Горпиніч
906bfd24a4 Translated using Weblate (Ukrainian)
Some checks failed
docker / docker_dev (push) Has been cancelled
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-02-02 07:03:04 +01:00
Massimo Pissarello
8f48172940 Translated using Weblate (Italian)
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-02-02 07:03:03 +01:00
Sylvain Pichon
736304eb8a Translated using Weblate (French)
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-02-02 07:03:02 +01:00
Anonymous
5fce3c79b0 Translated using Weblate (Ukrainian)
Some checks are pending
docker / docker_dev (push) Waiting to run
Currently translated at 99.8% (752 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-02-01 06:14:17 +01:00
Anonymous
81c1f65816 Translated using Weblate (Catalan)
Currently translated at 99.8% (752 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-02-01 06:14:17 +01:00
Anonymous
edfaadf682 Translated using Weblate (Turkish)
Currently translated at 22.0% (166 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-02-01 06:14:17 +01:00
Anonymous
0a51d5fe79 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 87.9% (662 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-02-01 06:14:17 +01:00
Anonymous
893063c695 Translated using Weblate (Polish)
Currently translated at 88.4% (666 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-02-01 06:14:17 +01:00
Anonymous
da5cf4a8f1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 32.5% (245 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-02-01 06:14:17 +01:00
Anonymous
1e5a4e96e4 Translated using Weblate (Italian)
Currently translated at 99.8% (752 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-02-01 06:14:16 +01:00
Anonymous
74d7a7853a Translated using Weblate (Russian)
Currently translated at 99.7% (751 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-02-01 06:14:16 +01:00
Anonymous
63469007ef Translated using Weblate (Norwegian Bokmål)
Currently translated at 87.6% (660 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-02-01 06:14:16 +01:00
Anonymous
f5b875e2df Translated using Weblate (French)
Currently translated at 99.8% (752 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-02-01 06:14:16 +01:00
Anonymous
d18efb2103 Translated using Weblate (Spanish)
Currently translated at 96.5% (727 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-02-01 06:14:15 +01:00
Anonymous
e2cdce2f39 Translated using Weblate (German)
Currently translated at 89.3% (673 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-02-01 06:14:15 +01:00
jokob-sk
c855d50999 docs + sorting #983
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-02-01 13:07:46 +11:00
jokob-sk
9d8b147e40 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-01-31 07:04:19 +11:00
jokob-sk
3aa9be7019 docs #982 2025-01-31 07:04:15 +11:00
Hosted Weblate
72b3d5eb6d Merge branch 'origin/main' into Weblate.
Some checks failed
docker / docker_dev (push) Has been cancelled
2025-01-26 23:36:17 +00:00
anton garcias
83bc406ed6 Translated using Weblate (Catalan)
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-01-26 23:36:16 +00:00
jokob-sk
e6e1c79d6a docs 2025-01-27 10:35:57 +11:00
Jokob @NetAlertX
e0616f72fe Merge pull request #981 from vladaurosh/main
Update default PUID and PGID, and update documentation
2025-01-27 09:20:28 +11:00
vladaurosh
696403ac20 Update FILE_PERMISSIONS.md 2025-01-26 21:57:54 +00:00
vladaurosh
c946a5335a Update README.md 2025-01-26 18:18:04 +00:00
vladaurosh
9610810891 Set uid/gid to previous default 102/82 2025-01-26 17:33:30 +00:00
Jokob @NetAlertX
2ad7f02255 Merge pull request #980 from vladaurosh/main
Some checks are pending
docker / docker_dev (push) Waiting to run
Adding option to set user ID and GID
2025-01-26 13:40:13 +11:00
root
431543ba80 adding option to set user ID and GID 2025-01-26 01:46:38 +00:00
jokob-sk
09d2e68479 Undiscoverables - UNDIS removal #979
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-01-26 10:23:21 +11:00
jokob-sk
896b8b7641 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-01-26 10:21:01 +11:00
jokob-sk
8d607aac96 css fixes, docs 2025-01-26 10:20:46 +11:00
Максим Горпиніч
c95a371ad9 Translated using Weblate (Ukrainian)
Some checks are pending
docker / docker_dev (push) Waiting to run
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-01-25 13:02:18 +01:00
Sylvain Pichon
4b3ff048dc Translated using Weblate (French)
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-01-25 13:02:17 +01:00
Massimo Pissarello
3267762280 Translated using Weblate (Italian)
Some checks are pending
docker / docker_dev (push) Waiting to run
Currently translated at 100.0% (753 of 753 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-01-25 06:31:12 +01:00
Hosted Weblate
885a470585 Merge branch 'origin/main' into Weblate. 2025-01-25 00:37:31 +00:00
Safeguard
d0f4faca51 Translated using Weblate (Russian)
Currently translated at 100.0% (752 of 752 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-01-25 00:37:30 +00:00
jokob-sk
4443c69d31 Filters UI_columns_filters #953 2025-01-25 11:37:05 +11:00
Jokob @NetAlertX
890e533969 Merge pull request #976 from cvc90/NetAlertX-Changing-absolute-path-url-to-relative-path-url-in-common.js-file
Some checks are pending
docker / docker_dev (push) Waiting to run
Changed the "absolute URL" target to "relative URL" in common.js
2025-01-25 07:51:51 +11:00
Carlos V.
d7b9bb447f Update common.js
Change absolute path url /php/server/query_json.php to relative path url php/server/query_json.php
2025-01-24 17:17:52 +01:00
jokob-sk
c63f424c7d LOADED_PLUGINS docker variable #975
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-01-24 20:05:42 +11:00
jokob-sk
dd1580e536 asus and logging #972 2025-01-24 18:58:10 +11:00
jokob-sk
630e4f6327 asus DHCPLSS guide #963
Some checks failed
docker / docker_dev (push) Has been cancelled
2025-01-22 08:37:55 +11:00
Jokob @NetAlertX
cb8af32553 Merge pull request #970 from labmonkey/asuswrt-import
Some checks are pending
docker / docker_dev (push) Waiting to run
[ASUSWRT] Added router port to configurtation
2025-01-21 06:43:42 +11:00
jokob-sk
d469a9ded4 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-01-20 23:42:48 +11:00
jokob-sk
c8a40920b4 cleanup, faster devices screen update #967 #923 2025-01-20 23:42:24 +11:00
Максим Горпиніч
b0cd9acb79 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (752 of 752 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-01-20 08:35:13 +01:00
Anonymous
6129f31a24 Translated using Weblate (Polish)
Some checks are pending
docker / docker_dev (push) Waiting to run
Currently translated at 88.6% (667 of 752 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-01-20 06:17:17 +01:00
Massimo Pissarello
3eb8f39b5c Translated using Weblate (Italian)
Currently translated at 100.0% (752 of 752 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-01-20 06:17:17 +01:00
jokob-sk
5b1002620b cleanup, css, rebase to alpine 3.21 #968 2025-01-20 14:55:26 +11:00
Pawel Derehajlo
e50d757f57 [ASUSWRT] Added router port to configurtation 2025-01-20 02:07:47 +01:00
Jokob @NetAlertX
5110a3c2f3 Merge pull request #966 from vladaurosh/main
Using busybox crond instead of dcron, starting it with s6
2025-01-20 11:47:14 +11:00
root
abf7be5958 adding new line for pem file 2025-01-19 22:23:52 +00:00
root
82708bd5df Fixing path to cert file 2025-01-19 22:19:00 +00:00
root
b5dce3f6aa Fixing crond issues #945 and #965 2025-01-19 22:11:32 +00:00
jokob-sk
5562ae7add docs + wf
Some checks are pending
docker / docker_dev (push) Waiting to run
2025-01-19 23:19:26 +11:00
243 changed files with 14018 additions and 6538 deletions

View File

@@ -46,7 +46,7 @@ body:
- type: checkboxes
attributes:
label: Can I help implement this? 👩‍💻👨‍💻
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://jokob-sk.github.io/NetAlertX/DEV_ENV_SETUP/
options:
- label: "Yes"
- label: "No"

View File

@@ -7,7 +7,7 @@ body:
label: Is there an existing issue for this?
description: Please search to see if an open or closed issue already exists for the bug you encountered.
options:
- label: I have searched the existing open and closed issues and I checked the docs https://github.com/jokob-sk/NetAlertX/tree/main/docs
- label: I have searched the existing open and closed issues and I checked the docs https://jokob-sk.github.io/NetAlertX/
required: true
- type: checkboxes
attributes:

72
.github/ISSUE_TEMPLATE/setup-help.yml vendored Executable file
View File

@@ -0,0 +1,72 @@
name: Setup help
description: 'When submitting an issue enable LOG_LEVEL="trace" and re-search first.'
labels: ['Setup 📥']
body:
- type: checkboxes
attributes:
label: Did I research?
description: Please confirm you checked the usual places before opening a setup support request.
options:
- label: I have searched the docs https://jokob-sk.github.io/NetAlertX/
required: true
- label: I have searched the existing open and closed issues
required: true
- label: I confirm my SCAN_SUBNETS is configured and tested as per https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md
required: true
- type: checkboxes
attributes:
label: The issue occurs in the following browsers. Select at least 2.
description: This step helps me understand if this is a cache or browser-specific issue.
options:
- label: "Firefox"
- label: "Chrome"
- label: "Other (unsupported) - PRs welcome"
- label: "N/A - This is an issue with the backend"
- type: textarea
attributes:
label: What I want to do
description: Describe what you want to achieve.
validations:
required: false
- type: textarea
attributes:
label: Relevant settings you changed
description: |
Paste a screenshot or setting values of the settings you changed.
validations:
required: false
- type: textarea
attributes:
label: docker-compose.yml
description: |
Paste your `docker-compose.yml`
render: python
validations:
required: false
- type: dropdown
attributes:
label: What installation are you running?
options:
- Production (netalertx)
- Dev (netalertx-dev)
- Home Assistant (addon)
validations:
required: true
- type: textarea
attributes:
label: app.log
description: |
Logs with debug enabled (https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md) ⚠
***Generally speaking, all bug reports should have logs provided.***
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
Additionally, any additional info? Screenshots? References? Anything that will give us more context about the issue you are encountering!
You can use `tail -100 /app/log/app.log` in the container if you have trouble getting to the log files.
validations:
required: false
- type: checkboxes
attributes:
label: Debug enabled
description: I confirm I enabled `debug`
options:
- label: I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.
required: true

28
.github/workflows/code_checks.yml vendored Executable file
View File

@@ -0,0 +1,28 @@
name: URL Path Check
on:
push:
branches:
- main
tags:
- '*.*.*'
pull_request:
branches:
- main
jobs:
check-url-paths:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for absolute path URLs
run: |
if grep -r -E "\burl:\s*['\"]\/php" --include=\*.{js,php} .; then
echo "❌ Found absolute path URLs starting with '/php/'. Please use relative paths."
exit 1
else
echo "✅ No absolute path URLs found."
fi

View File

@@ -1,15 +1,14 @@
---
name: docker
on:
push:
branches:
- '**'
- main
tags:
- '*.*.*'
pull_request:
branches:
- master
- main
jobs:
docker_dev:
@@ -37,7 +36,7 @@ jobs:
- name: Get release version
id: get_version
run: echo "::set-output name=version::${{ 'Dev' }}"
run: echo "version=Dev" >> $GITHUB_OUTPUT
- name: Create .VERSION file
run: echo "${{ steps.get_version.outputs.version }}" >> .VERSION
@@ -46,13 +45,11 @@ jobs:
id: meta
uses: docker/metadata-action@v4
with:
# list of Docker images to use as base name for tags
images: |
ghcr.io/jokob-sk/netalertx-dev
jokobsk/netalertx-dev
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
@@ -60,7 +57,7 @@ jobs:
type=semver,pattern={{major}}
type=sha
- name: Log in to Github Container registry
- name: Log in to Github Container Registry (GHCR)
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -74,10 +71,6 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# # Disable this after use
# - name: Prune Docker Builder
# run: docker builder prune --force
- name: Build and push
uses: docker/build-push-action@v3
with:
@@ -86,6 +79,3 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# # ⚠ disable cache if build is failing to download debian packages
# cache-from: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache
# cache-to: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache,mode=max

View File

@@ -48,7 +48,7 @@ jobs:
with:
# list of Docker images to use as base name for tags
images: |
jokobsk/pi.alert
ghcr.io/jokob-sk/netalertx
jokobsk/netalertx
# generate Docker tags based on the following events/attributes
tags: |

25
.github/workflows/mkdocs.yml vendored Executable file
View File

@@ -0,0 +1,25 @@
name: Deploy MkDocs
on:
push:
branches:
- main # Change if your default branch is different
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install MkDocs
run: |
pip install mkdocs mkdocs-material && pip install mkdocs-github-admonitions-plugin
- name: Deploy MkDocs
run: mkdocs gh-deploy --force

View File

@@ -4,29 +4,50 @@ on:
types: [published]
jobs:
post-release:
post-discord:
runs-on: ubuntu-latest
steps:
- name: Wait for 15 minutes
run: sleep 900 # 15 minutes delay
# Post to Twitter
- name: Post to Twitter
uses: gr2m/twitter-together@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }}
TWITTER_API_SECRET: ${{ secrets.TWITTER_API_SECRET }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
with:
tweet: |
🎉 New release: **${{ github.event.release.name }}** is live! 🚀
Check it out here: ${{ github.event.release.html_url }}
# Post to Discord
- name: Post to Discord
run: |
curl -X POST -H "Content-Type: application/json" \
-d '{"content": "🎉 New release: **${{ github.event.release.name }}** is live! 🚀\nCheck it out here: ${{ github.event.release.html_url }}"}' \
${{ secrets.DISCORD_WEBHOOK_URL }}
post-twitter:
runs-on: ubuntu-latest
steps:
- name: Wait for 15 minutes
run: sleep 900 # 15 minutes delay
- name: Checkout repository
uses: actions/checkout@v3
- name: Set Git config
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"
- name: Create tweet file
run: |
echo "🎉 New release: **${{ github.event.release.name }}** is live! 🚀" > .github/tweet.md
echo "Check it out here: ${{ github.event.release.html_url }}" >> .github/tweet.md
git add .github/tweet.md
git commit -m "Add release tweet for ${{ github.event.release.name }}"
- name: Push changes
run: |
git push https://github.com/${{ github.repository }}.git HEAD:main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Tweet
uses: twitter-together/action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }}
TWITTER_API_SECRET_KEY: ${{ secrets.TWITTER_API_SECRET_KEY }}

View File

@@ -1,11 +1,11 @@
FROM alpine:3.20 AS builder
FROM alpine:3.21 AS builder
ARG INSTALL_DIR=/app
ENV PYTHONUNBUFFERED=1
# Install build dependencies
RUN apk add --no-cache bash python3 python3-dev gcc musl-dev libffi-dev openssl-dev git\
RUN apk add --no-cache bash shadow python3 python3-dev gcc musl-dev libffi-dev openssl-dev git \
&& python -m venv /opt/venv
# Enable venv
@@ -13,34 +13,21 @@ ENV PATH="/opt/venv/bin:$PATH"
COPY . ${INSTALL_DIR}/
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask netifaces tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros git+https://github.com/foreign-sub/aiofreepybox.git \
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros git+https://github.com/foreign-sub/aiofreepybox.git \
&& bash -c "find ${INSTALL_DIR} -type d -exec chmod 750 {} \;" \
&& bash -c "find ${INSTALL_DIR} -type f -exec chmod 640 {} \;" \
&& bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"
# Append Iliadbox certificate to aiofreepybox
RUN printf "\n-----BEGIN CERTIFICATE-----\n\
MIICOjCCAcCgAwIBAgIUI0Tu7zsrBJACQIZgLMJobtbdNn4wCgYIKoZIzj0EAwIw\n\
TDELMAkGA1UEBhMCSVQxDjAMBgNVBAgMBUl0YWx5MQ4wDAYDVQQKDAVJbGlhZDEd\n\
MBsGA1UEAwwUSWxpYWRib3ggRUNDIFJvb3QgQ0EwHhcNMjAxMTI3MDkzODEzWhcN\n\
NDAxMTIyMDkzODEzWjBMMQswCQYDVQQGEwJJVDEOMAwGA1UECAwFSXRhbHkxDjAM\n\
BgNVBAoMBUlsaWFkMR0wGwYDVQQDDBRJbGlhZGJveCBFQ0MgUm9vdCBDQTB2MBAG\n\
ByqGSM49AgEGBSuBBAAiA2IABMryJyb2loHNAioY8IztN5MI3UgbVHVP/vZwcnre\n\
ZvJOyDvE4HJgIti5qmfswlnMzpNbwf/MkT+7HAU8jJoTorRm1wtAnQ9cWD3Ebv79\n\
RPwtjjy3Bza3SgdVxmd6fWPUKaNjMGEwHQYDVR0OBBYEFDUij/4lpoJ+kOXRyrcM\n\
jf2RPzOqMB8GA1UdIwQYMBaAFDUij/4lpoJ+kOXRyrcMjf2RPzOqMA8GA1UdEwEB\n\
/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQC6eUV1\n\
pFh4UpJOTc1JToztN4ttnQR6rIzxMZ6mNCe+nhjkohWp24pr7BpUYSbEizYCMAQ6\n\
LCiBKV2j7QQGy7N1aBmdur17ZepYzR1YV0eI+Kd978aZggsmhjXENQYVTmm/XA==\n\
-----END CERTIFICATE-----\n" >> /opt/venv/lib/python3.12/site-packages/aiofreepybox/freebox_certificates.pem
RUN cat ${INSTALL_DIR}/install/freebox_certificate.pem >> /opt/venv/lib/python3.12/site-packages/aiofreepybox/freebox_certificates.pem
# second stage
FROM alpine:3.20 AS runner
FROM alpine:3.21 AS runner
ARG INSTALL_DIR=/app
COPY --from=builder /opt/venv /opt/venv
COPY --from=builder /usr/sbin/usermod /usr/sbin/groupmod /usr/sbin/
# Enable venv
ENV PATH="/opt/venv/bin:$PATH"
@@ -54,11 +41,10 @@ ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
# ❗ IMPORTANT - if you modify this file modify the /install/install_dependecies.sh file as well ❗
RUN apk update --no-cache \
&& apk add --no-cache bash zip lsblk gettext-envsubst sudo mtr tzdata s6-overlay \
&& apk add --no-cache bash libbsd zip lsblk gettext-envsubst sudo mtr tzdata s6-overlay \
&& apk add --no-cache curl arp-scan iproute2 iproute2-ss nmap nmap-scripts traceroute nbtscan avahi avahi-tools openrc dbus net-tools net-snmp-tools bind-tools awake ca-certificates \
&& apk add --no-cache sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session \
&& apk add --no-cache python3 nginx \
&& apk add --no-cache dcron \
&& ln -s /usr/bin/awake /usr/bin/wakeonlan \
&& bash -c "install -d -m 750 -o nginx -g www-data ${INSTALL_DIR} ${INSTALL_DIR}" \
&& rm -f /etc/nginx/http.d/default.conf
@@ -66,7 +52,7 @@ RUN apk update --no-cache \
COPY --from=builder --chown=nginx:www-data ${INSTALL_DIR}/ ${INSTALL_DIR}/
# Add crontab file
COPY install/crontab /etc/crontabs/root
COPY --chmod=600 --chown=root:root install/crontab /etc/crontabs/root
# Start all required services
RUN ${INSTALL_DIR}/dockerfiles/start.sh

View File

@@ -43,7 +43,7 @@ RUN phpenmod -v 8.2 sqlite3
RUN apt-get install -y python3-venv
RUN python3 -m venv myenv
RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask netifaces tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros "
RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros "
# Create a buildtimestamp.txt to later check if a new version was released
RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt

View File

@@ -6,10 +6,10 @@
# NetAlertX - Network, presence scanner and alert framework
Get visibility of what's going on on your WIFI/LAN network and enable presence detection of important devices. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
Get visibility of what's going on on your WIFI/LAN network and enable presence detection of important devices. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://github.com/jokob-sk/NetAlertX/tree/main/docs) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
|----------------------| ----------------------| ----------------------| ----------------------| ----------------------|
![showcase][showcase]
@@ -30,7 +30,7 @@ Get visibility of what's going on on your WIFI/LAN network and enable presence d
### Scanners
The app scans your network for **New devices**, **New connections** (re-connections), **Disconnections**, **"Always Connected" devices down**, Devices **IP changes** and **Internet IP address changes**. Discovery & scan methods include: **arp-scan**, **Pi-hole - DB import**, **Pi-hole - DHCP leases import**, **Generic DHCP leases import**, **UNIFI controller import**, **SNMP-enabled router import**. Check the [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) docs for a full lits of avaliable plugins.
The app scans your network for **New devices**, **New connections** (re-connections), **Disconnections**, **"Always Connected" devices down**, Devices **IP changes** and **Internet IP address changes**. Discovery & scan methods include: **arp-scan**, **Pi-hole - DB import**, **Pi-hole - DHCP leases import**, **Generic DHCP leases import**, **UNIFI controller import**, **SNMP-enabled router import**. Check the [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) docs for a full lits of avaliable plugins.
### Notification gateways
@@ -39,7 +39,7 @@ Send notifications to more than 80+ services, including Telegram via [Apprise](h
### Integrations and Plugins
Feed your data and device changes into [Home Assistant](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HOME_ASSISTANT.md), read [API endpoints](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md), or use [Webhooks](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md) to setup custom automation flows. You can also
build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) in as little as [15 minutes](https://www.youtube.com/watch?v=cdbxlwiWhv8).
build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) in as little as [15 minutes](https://www.youtube.com/watch?v=cdbxlwiWhv8).
## 📚 Documentation
@@ -119,7 +119,6 @@ Proudly using [Weblate](https://hosted.weblate.org/projects/pialert/). Help out
[network]: ./docs/img/network.png "Screen 5"
[settings]: ./docs/img/settings.png "Screen 6"
[showcase]: ./docs/img/showcase.gif "Screen 6"
[help_faq]: ./docs/img/help_faq.png "Screen 7"
[sync_hub]: ./docs/img/sync_hub.png "Screen 8"
[notification_center]: ./docs/img/notification_center.png "Screen 8"
[sent_reports_text]: ./docs/img/sent_reports_text.png "Screen 8"

View File

@@ -5,8 +5,9 @@ LOG_FILE="${INSTALL_DIR}/log/execution_queue.log"
# Check if there are any entries with cron_restart_backend
if grep -q "cron_restart_backend" "$LOG_FILE"; then
# Kill all python processes (restart handled by s6 overlay)
pkill -f "python " && echo 'done'
# Restart python application using s6
s6-svc -r /var/run/s6-rc/servicedirs/netalertx
echo 'done'
# Remove all lines containing cron_restart_backend from the log file
sed -i '/cron_restart_backend/d' "$LOG_FILE"

View File

@@ -28,6 +28,8 @@ services:
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases
- ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db
- ${DEV_LOCATION}/mkdocs.yml:/app/mkdocs.yml
- ${DEV_LOCATION}/docs:/app/docs
- ${DEV_LOCATION}/server:/app/server
- ${DEV_LOCATION}/test:/app/test
- ${DEV_LOCATION}/dockerfiles:/app/dockerfiles
@@ -50,7 +52,6 @@ services:
- ${DEV_LOCATION}/front/events.php:/app/front/events.php
- ${DEV_LOCATION}/front/plugins.php:/app/front/plugins.php
- ${DEV_LOCATION}/front/pluginsCore.php:/app/front/pluginsCore.php
- ${DEV_LOCATION}/front/help_faq.php:/app/front/help_faq.php
- ${DEV_LOCATION}/front/index.php:/app/front/index.php
- ${DEV_LOCATION}/front/maintenance.php:/app/front/maintenance.php
- ${DEV_LOCATION}/front/network.php:/app/front/network.php
@@ -60,9 +61,10 @@ services:
- ${DEV_LOCATION}/front/cloud_services.php:/app/front/cloud_services.php
- ${DEV_LOCATION}/front/report.php:/app/front/report.php
- ${DEV_LOCATION}/front/workflows.php:/app/front/workflows.php
- ${DEV_LOCATION}/front/workflowsCore.php:/app/front/workflowsCore.php
- ${DEV_LOCATION}/front/appEvents.php:/app/front/appEvents.php
- ${DEV_LOCATION}/front/appEventsCore.php:/app/front/appEventsCore.php
- ${DEV_LOCATION}/front/multiEditCore.php:/app/front/multiEditCore.php
- ${DEV_LOCATION}/front/donations.php:/app/front/donations.php
- ${DEV_LOCATION}/front/plugins:/app/front/plugins
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
# ---------------------------------------------------------------------------
@@ -72,4 +74,5 @@ services:
- PORT=${PORT}
# ❗ DANGER ZONE BELOW - Setting ALWAYS_FRESH_INSTALL=true will delete the content of the /db & /config folders
- ALWAYS_FRESH_INSTALL=${ALWAYS_FRESH_INSTALL}
# - LOADED_PLUGINS=["DHCPLSS","PIHOLE","ASUSWRT","FREEBOX"]

View File

@@ -6,7 +6,7 @@
# NetAlertX - Network scanner & notification framework
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://github.com/jokob-sk/NetAlertX/tree/main/docs) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
|----------------------| ----------------------| ----------------------| ----------------------| ----------------------|
<a href="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/GENERAL/github_social_image.jpg" target="_blank">
@@ -21,31 +21,35 @@ Head to [https://netalertx.com/](https://netalertx.com/) for more gifs and scree
## 📕 Basic Usage
> [!WARNING]
> You will have to run the container on the `host` network and specify `SCAN_SUBNETS` unless you use other [plugin scanners](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md). The initial scan can take a few minutes, so please wait 5-10 minutes for the initial discovery to finish.
> You will have to run the container on the `host` network and specify `SCAN_SUBNETS` unless you use other [plugin scanners](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md). The initial scan can take a few minutes, so please wait 5-10 minutes for the initial discovery to finish.
```yaml
docker run -d --rm --network=host \
-v local_path/config:/app/config \
-v local_path/db:/app/db \
--mount type=tmpfs,target=/app/api \
-e PUID=200 -e PGID=300 \
-e TZ=Europe/Berlin \
-e PORT=20211 \
jokobsk/netalertx:latest
ghcr.io/jokob-sk/netalertx:latest
```
See alternative [docked-compose examples](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md).
### Docker environment variables
| Variable | Description | Default |
| :------------- |:-------------| -----:|
| Variable | Description | Example Value |
| :------------- |:------------------------| -----:|
| `PORT` |Port of the web interface | `20211` |
| `PUID` |Application User UID | `102` |
| `PGID` |Application User GID | `82` |
| `LISTEN_ADDR` |Set the specific IP Address for the listener address for the nginx webserver (web interface). This could be useful when using multiple subnets to hide the web interface from all untrusted networks. | `0.0.0.0` |
|`TZ` |Time zone to display stats correctly. Find your time zone [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | `Europe/Berlin` |
|`APP_CONF_OVERRIDE` | JSON override for settings, e.g. `{"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","GRAPHQL_PORT":"20212"}` | `N/A` |
|`ALWAYS_FRESH_INSTALL` | If `true` will delete the content of the `/db` & `/config` folders. For testing purposes. Can be coupled with [watchtower](https://github.com/containrrr/watchtower) to have an always freshly installed `netalertx`/`netalertx-dev` image. | `N/A` |
|`LOADED_PLUGINS` | Default [plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) to load. Plugins cannot be loaded with `APP_CONF_OVERRIDE`, you need to use this variable instead and then specify the plugins settings with `APP_CONF_OVERRIDE`. | `["PIHOLE","ASUSWRT"]` |
|`APP_CONF_OVERRIDE` | JSON override for settings (except `LOADED_PLUGINS`). | `{"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","GRAPHQL_PORT":"20212"}` |
|`ALWAYS_FRESH_INSTALL` | ⚠ If `true` will delete the content of the `/db` & `/config` folders. For testing purposes. Can be coupled with [watchtower](https://github.com/containrrr/watchtower) to have an always freshly installed `netalertx`/`netalertx-dev` image. | `true` |
> You can override the default GraphQL port setting `GRAPHQL_PORT` (set to `20212`) by using the `APP_CONF_OVERRIDE` env variable.
> You can override the default GraphQL port setting `GRAPHQL_PORT` (set to `20212`) by using the `APP_CONF_OVERRIDE` env variable. `LOADED_PLUGINS` and settings in `APP_CONF_OVERRIDE` can be specified via the UI as well.
### Docker paths
@@ -58,7 +62,7 @@ See alternative [docked-compose examples](https://github.com/jokob-sk/NetAlertX/
| ✅ | `:/app/db` | Folder which will contain the `app.db` database file |
| | `:/app/log` | Logs folder useful for debugging if you have issues setting up the container |
| | `:/app/api` | A simple [API endpoint](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md) containing static (but regularly updated) json and other files. |
| | `:/app/front/plugins/<plugin>/ignore_plugin` | Map a file `ignore_plugin` to ignore a plugin. Plugins can be soft-disabled via settings. More in the [Plugin docs](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md). |
| | `:/app/front/plugins/<plugin>/ignore_plugin` | Map a file `ignore_plugin` to ignore a plugin. Plugins can be soft-disabled via settings. More in the [Plugin docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md). |
| | `:/etc/resolv.conf` | Use a custom `resolv.conf` file for [better name resolution](https://github.com/jokob-sk/NetAlertX/blob/main/docs/REVERSE_DNS.md). |
> Use separate `db` and `config` directories, do not nest them.
@@ -68,7 +72,7 @@ See alternative [docked-compose examples](https://github.com/jokob-sk/NetAlertX/
- If unavailable, the app generates a default `app.conf` and `app.db` file on the first run.
- The preferred way is to manage the configuration via the Settings section in the UI, if UI is inaccessible you can modify [app.conf](https://github.com/jokob-sk/NetAlertX/tree/main/back) in the `/app/config/` folder directly
### Setting up scanners
#### Setting up scanners
You have to specify which network(s) should be scanned. This is done by entering subnets that are accessible from the host. If you use the default `ARPSCAN` plugin, you have to specify at least one valid subnet and interface in the `SCAN_SUBNETS` setting. See the documentation on [How to set up multiple SUBNETS, VLANs and what are limitations](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) for troubleshooting and more advanced scenarios.
@@ -77,19 +81,18 @@ If you are running PiHole you can synchronize devices directly. Check the [PiHol
> [!NOTE]
> You can bulk-import devices via the [CSV import method](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md).
#### 🧭 Community guides
#### Community guides
You can read or watch several [community configuration guides](https://github.com/jokob-sk/NetAlertX/blob/main/docs/COMMUNITY_GUIDES.md) in Chinese, Korean, German, or French.
> Please note these might be outdated. Rely on official documentation first.
### **Common issues**
#### Common issues
💡 Before creating a new issue, please check if a similar issue was [already resolved](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed).
- Before creating a new issue, please check if a similar issue was [already resolved](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed).
- Check also common issues and [debugging tips](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md).
⚠ Check also common issues and [debugging tips](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md).
## ❤ Support me
## 💙 Support me
| [![GitHub](https://i.imgur.com/emsRCPh.png)](https://github.com/sponsors/jokob-sk) | [![Buy Me A Coffee](https://i.imgur.com/pIM6YXL.png)](https://www.buymeacoffee.com/jokobsk) | [![Patreon](https://i.imgur.com/MuYsrq1.png)](https://www.patreon.com/user?u=84385063) |
| --- | --- | --- |

View File

@@ -1,8 +1,36 @@
#!/usr/bin/with-contenv bash
echo "---------------------------------------------------------"
echo "[INSTALL] Run init.sh"
echo "---------------------------------------------------------"
echo "---------------------------------------------------------
[INSTALL] Run init.sh
---------------------------------------------------------"
DEFAULT_PUID=102
DEFAULT_GID=82
PUID=${PUID:-${DEFAULT_PUID}}
PGID=${PGID:-${DEFAULT_GID}}
echo "[INSTALL] Setting up user UID and GID"
if ! groupmod -o -g "$PGID" www-data && [ "$PGID" != "$DEFAULT_GID" ] ; then
echo "Failed to set user GID to ${PGID}, trying with default GID ${DEFAULT_GID}"
groupmod -o -g "$DEFAULT_GID" www-data
fi
if ! usermod -o -u "$PUID" nginx && [ "$PUID" != "$DEFAULT_PUID" ] ; then
echo "Failed to set user UID to ${PUID}, trying with default PUID ${DEFAULT_PUID}"
usermod -o -u "$DEFAULT_PUID" nginx
fi
echo "
---------------------------------------------------------
GID/UID
---------------------------------------------------------
User UID: $(id -u nginx)
User GID: $(getent group www-data | cut -d: -f3)
---------------------------------------------------------"
chown nginx:nginx /run/nginx/ /var/log/nginx/ /var/lib/nginx/ /var/lib/nginx/tmp/
chgrp www-data /var/www/localhost/htdocs/
export INSTALL_DIR=/app # Specify the installation directory here
@@ -26,8 +54,6 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
echo "[INSTALL] Copy starter ${DB_FILE} and ${CONF_FILE} if they don't exist"
# DANGER ZONE: ALWAYS_FRESH_INSTALL
if [ "$ALWAYS_FRESH_INSTALL" = true ]; then
echo "[INSTALL] ❗ ALERT /db and /config folders are cleared because the ALWAYS_FRESH_INSTALL is set to: $ALWAYS_FRESH_INSTALL"
@@ -55,7 +81,7 @@ else
echo "Config file saved to ${INSTALL_DIR}/config/app_conf_override.json"
fi
# 🔻 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2024
# 🔻 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2025
# Check if pialert.db exists, then create a symbolic link to app.db
if [ -f "${INSTALL_DIR_OLD}/db/${OLD_APP_NAME}.db" ]; then
@@ -66,9 +92,11 @@ fi
if [ -f "${INSTALL_DIR_OLD}/config/${OLD_APP_NAME}.conf" ]; then
ln -s "${INSTALL_DIR_OLD}/config/${OLD_APP_NAME}.conf" "${INSTALL_DIR}/config/${CONF_FILE}"
fi
# 🔺 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2024
# 🔺 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2025
# Copy starter .db and .conf if they don't exist
echo "[INSTALL] Copy starter ${DB_FILE} and ${CONF_FILE} if they don't exist"
# Copy starter app.db, app.conf if they don't exist
cp -na "${INSTALL_DIR}/back/${CONF_FILE}" "${INSTALL_DIR}/config/${CONF_FILE}"
cp -na "${INSTALL_DIR}/back/${DB_FILE}" "${FULL_FILEDB_PATH}"
@@ -83,6 +111,13 @@ if [ -n "${TZ}" ]; then
echo $TZ > /etc/timezone
fi
# if custom variables not set we do not need to do anything
if [ -n "${LOADED_PLUGINS}" ]; then
FILECONF="${INSTALL_DIR}/config/${CONF_FILE}"
echo "[INSTALL] Setup custom LOADED_PLUGINS variable"
sed -i "\#^LOADED_PLUGINS=#c\LOADED_PLUGINS=${LOADED_PLUGINS}" "${FILECONF}"
fi
echo "[INSTALL] Setup NGINX"
echo "Setting webserver to address ($LISTEN_ADDR) and port ($PORT)"
envsubst '$INSTALL_DIR $LISTEN_ADDR $PORT' < "${INSTALL_DIR}/install/netalertx.template.conf" > "${NGINX_CONFIG_FILE}"
@@ -108,12 +143,12 @@ fi
# Create the execution_queue.log and app_front.log files if they don't exist
touch "${INSTALL_DIR}"/log/{app.log,execution_queue.log,app_front.log,app.php_errors.log,stderr.log,stdout.log,db_is_locked.log}
touch "${INSTALL_DIR}"/api/user_notifications.json
# Create plugins sub-directory if it doesn't exist in case a custom log folder is used
mkdir -p "${INSTALL_DIR}"/log/plugins
echo "[INSTALL] Fixing permissions after copied starter config & DB"
chown -R nginx:www-data "${INSTALL_DIR}"/{config,log,db,api}
chown -R nginx:www-data "${INSTALL_DIR}"/api/user_notifications.json
chown -R nginx:www-data "${INSTALL_DIR}"
chmod 750 "${INSTALL_DIR}"/{config,log,db}
find "${INSTALL_DIR}"/{config,log,db} -type f -exec chmod 640 {} \;
@@ -125,10 +160,6 @@ if [ ! -f "${INSTALL_DIR}/front/buildtimestamp.txt" ]; then
chown nginx:www-data "${INSTALL_DIR}/front/buildtimestamp.txt"
fi
# Start crond service in the background
echo "[INSTALL] Starting crond service..."
crond -f -d 8 > /dev/null 2>&1 &
echo -e "
[ENV] PATH is ${PATH}
[ENV] PORT is ${PORT}

View File

@@ -20,7 +20,14 @@ echo "longrun" > /etc/s6-overlay/s6-rc.d/php-fpm/type
echo "longrun" > /etc/s6-overlay/s6-rc.d/nginx/type
echo "longrun" > /etc/s6-overlay/s6-rc.d/$APP_NAME/type
echo -e "${INSTALL_DIR}/dockerfiles/init.sh" > /etc/s6-overlay/s6-rc.d/SetupOneshot/up
echo -e "#!/bin/execlineb -P\n/usr/sbin/crond -f -d 8" > /etc/s6-overlay/s6-rc.d/crond/run
echo -e '#!/bin/execlineb -P
if { echo
"
[INSTALL] Starting crond service...
" }' > /etc/s6-overlay/s6-rc.d/crond/run
echo -e "/usr/sbin/crond -f" >> /etc/s6-overlay/s6-rc.d/crond/run
echo -e "#!/bin/execlineb -P\n/usr/sbin/php-fpm83 -F" > /etc/s6-overlay/s6-rc.d/php-fpm/run
echo -e '#!/bin/execlineb -P\nnginx -g "daemon off;"' > /etc/s6-overlay/s6-rc.d/nginx/run
echo -e '#!/bin/execlineb -P
@@ -39,4 +46,4 @@ touch /etc/s6-overlay/s6-rc.d/nginx/dependencies.d/php-fpm
touch /etc/s6-overlay/s6-rc.d/$APP_NAME/dependencies.d/nginx
# this removes the current file
# rm -f $0
rm -f $0

View File

@@ -23,9 +23,9 @@ curl 'http://host:GRAPHQL_PORT/graphql' \
## API Endpoint: GraphQL
Endpoint URL: `php/server/query_graphql.php`
Host: `same as front end (web ui)`
Port: `20212` or as defined by the `GRAPHQL_PORT` setting
- Endpoint URL: `php/server/query_graphql.php`
- Host: `same as front end (web ui)`
- Port: `20212` or as defined by the `GRAPHQL_PORT` setting
### Example Query to Fetch Devices
@@ -126,9 +126,9 @@ The response will be in JSON format, similar to the following:
This API endpoint retrieves static files, that are periodically updated.
Endpoint URL: `php/server/query_json.php?file=<file name>`
Host: `same as front end (web ui)`
Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
- Endpoint URL: `php/server/query_json.php?file=<file name>`
- Host: `same as front end (web ui)`
- Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
### When are the endpoints updated
@@ -148,7 +148,7 @@ You can access the following files:
| `table_devices.json` | All of the available Devices detected by the app. |
| `table_plugins_events.json` | The list of the unprocessed (pending) notification events (plugins_events DB table). |
| `table_plugins_history.json` | The list of notification events history. |
| `table_plugins_objects.json` | The content of the plugins_objects table. Find more info on the [Plugin system here](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins)|
| `table_plugins_objects.json` | The content of the plugins_objects table. Find more info on the [Plugin system here](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md)|
| `language_strings.json` | The content of the language_strings table, which in turn is loaded from the plugins `config.json` definitions. |
| `table_custom_endpoint.json` | A custom endpoint generated by the SQL query specified by the `API_CUSTOM_SQL` setting. |
| `table_settings.json` | The content of the settings table. |
@@ -223,9 +223,9 @@ Example JSON of the `table_devices.json` endpoint with two Devices (database row
This API endpoint retrieves files from the `/app/log` folder.
Endpoint URL: `php/server/query_logs.php?file=<file name>`
Host: `same as front end (web ui)`
Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
- Endpoint URL: `php/server/query_logs.php?file=<file name>`
- Host: `same as front end (web ui)`
- Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
| File | Description |
|--------------------------|---------------------------------------------------------------|
@@ -248,9 +248,9 @@ Port: `20211` or as defined by the $PORT docker environment variable (same as th
To retrieve files from the `/app/config` folder.
Endpoint URL: `php/server/query_config.php?file=<file name>`
Host: `same as front end (web ui)`
Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
- Endpoint URL: `php/server/query_config.php?file=<file name>`
- Host: `same as front end (web ui)`
- Port: `20211` or as defined by the $PORT docker environment variable (same as the port for the web ui)
| File | Description |
|--------------------------|--------------------------------------------------|

View File

@@ -1,6 +1,8 @@
(DRAFT) Authelia support
## Authelia support
> [!WARNING]
>
> This is community contributed content and work in progress. Contributions are welcome.
```yaml
theme: dark

View File

@@ -1,16 +1,59 @@
# 💾 Backing things up
# Backing things up
> [!NOTE]
> To backup 99% of your configuration backup at least the `/app/config` folder. Please read the whole page (or at least "Scenario 2: Corrupted database") for details.
> Please also note that database definitions might change over versions. The safest way is to restore your older backups into the **same version** of the app and then gradually upgarde between releases to the latest version.
> Note that database definitions might change over time. The safest way is to restore your older backups into the **same version** of the app they were taken from and then gradually upgarde between releases to the latest version.
There are 3 artifacts that can be used to backup the application:
There are 4 artifacts that can be used to backup the application:
| File | Description | Limitations |
|-----------------------|-------------------------------|-------------------------------|
| `/db/app.db` | Database file(s) | The database file might be in an uncommitted state or corrupted |
| `/config/app.conf` | Configuration file | Can be overridden with the [`APP_CONF_OVERRIDE` env variable](https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles#docker-environment-variables). |
| `/config/devices.csv` | CSV file containing device information | Doesn't contain historical data |
| `/config/workflows.json` | A JSON file containing your workflows | N/A |
## Backup strategies
The safest approach to backups is to backup everything, by taking regular file system backups of the `/db` and `/config` folders (I use [Kopia](https://github.com/kopia/kopia)).
Arguably, the most time is spent setting up the device list, so if only one file is kept I'd recommend to have a latest backup of the `devices_<timestamp>.csv` or `devices.csv` file, followed by the `app.conf` and `workflows.json` files. You can also download `app.conf` and `devices.csv` file in the Maintenance section:
![Backup and Restore Section in Maintenance](./img/BACKUPS/Maintenance_Backup_Restore.png)
### Scenario 1: Full backup
End-result: Full restore
#### 💾 Source artifacts:
- `/app/db/app.db` (uncorrupted)
- `/app/config/app.conf`
- `/app/config/workflows.json`
#### 📥 Recovery:
To restore the application map the above files as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
### Scenario 2: Corrupted database
End-result: Partial restore (historical data and some plugin data will be missing)
#### 💾 Source artifacts:
- `/app/config/app.conf`
- `/app/config/devices_<timestamp>.csv` or `/app/config/devices.csv`
- `/app/config/workflows.json`
#### 📥 Recovery:
Even with a corrupted database you can recover what I would argue is 99% of the configuration.
- upload the `app.conf` and `workflows.json` files into the mounted `/app/config/` folder as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
- rename the `devices_<timestamp>.csv` to `devices.csv` and place it in the `/app/config` folder
- Restore the `devices.csv` backup via the [Maintenance section](./DEVICES_BULK_EDITING.md)
## Data and backup storage
@@ -18,7 +61,7 @@ To decide on a backup strategy, check where the data is stored:
### Core Configuration
The core application configuration is in the `app.conf` file (See [Settings System](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SETTINGS_SYSTEM.md) for details), such as:
The core application configuration is in the `app.conf` file (See [Settings System](./SETTINGS_SYSTEM.md) for details), such as:
- Notification settings
- Scanner settings
@@ -37,50 +80,11 @@ The core device data is backed up to the `devices_<timestamp>.csv` or `devices.c
### Historical data
Historical data is stored in the `app.db` database (See [Database overview](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DATABASE.md) for details). This data includes:
Historical data is stored in the `app.db` database (See [Database overview](./DATABASE.md) for details). This data includes:
- Plugin objects
- Plugin historical entries
- History of Events, Notifications, Workflow Events
- Presence history
## 🧭 Backup strategies
The safest approach to backups is to backup all of the above, by taking regular file system backups (I use [Kopia](https://github.com/kopia/kopia)).
Arguably, the most time is spent setting up the device list, so if only one file is kept I'd recommend to have a latest backup of the `devices_<timestamp>.csv` or `devices.csv` file, followed by the `app.conf` file. You can also download `app.conf` and `devices.csv` file in the Maintenance section:
![Backup and Restore Section in Maintenance](/docs/img/BACKUPS/Maintenance_Backup_Restore.png)
### Scenario 1: Full backup
End-result: Full restore
#### Source artifacts:
- `/app/db/app.db` (uncorrupted)
- `/app/config/app.conf`
#### Recovery:
To restore the application map the above files as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
### Scenario 2: Corrupted database
End-result: Partial restore (historical data & configurations from the Maintenance section will be missing)
#### Source artifacts:
- `/app/config/app.conf`
- `/app/config/devices_<timestamp>.csv` or `/app/config/devices.csv`
#### Recovery:
Even with a corrupted database you can recover what I would argue is 99% of the configuration.
- upload the `app.conf` file into the mounted `/app/config/` folder as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
- rename the `devices_<timestamp>.csv` to `devices.csv` and place it in the `/app/config` folder
- Restore the `devices.csv` backup via the [Maintenance section](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md)

57
docs/COMMON_ISSUES.md Executable file
View File

@@ -0,0 +1,57 @@
### Loading...
Often if the application is misconfigured the `Loading...` dialog is continuously displayed. This is most likely caused by the backed failing to start. The **Maintenance -> Logs** section should give you more details on what's happening. If there is no exception, check the Portainer log, or start the container in the foreground (without the `-d` parameter) to observe any exceptions. It's advisable to enable `trace` or `debug`. Check the [Debug tips](./DEBUG_TIPS.md) on detailed instructions.
### Incorrect SCAN_SUBNETS
One of the most common issues is not configuring `SCAN_SUBNETS` correctly. If this setting is misconfigured you will only see one or two devices in your devices list after a scan. Please read the [subnets docs](./SUBNETS.md) carefully to resolve this.
### Duplicate devices and notifications
The app uses the MAC address as an unique identifier for devices. If a new MAC is detected a new device is added to the application and corresponding notifications are triggered. This means that if the MAC of an existing device changes, the device will be logged as a new device. You can usually prevent this from happening by changing the device configuration (in Android, iOS, or Windows) for your network. See the [Random Macs](./RANDOM_MAC.md) guide for details.
### Permissions
Make sure you [File permissions](./FILE_PERMISSIONS.md) are set correctly.
* If facing issues (AJAX errors, can't write to DB, empty screen, etc,) make sure permissions are set correctly, and check the logs under `/app/log`.
* To solve permission issues you can try setting the owner and group of the `app.db` by executing the following on the host system: `docker exec netalertx chown -R www-data:www-data /app/db/app.db`.
* If still facing issues, try to map the app.db file (⚠ not folder) to `:/app/db/app.db` (see [docker-compose Examples](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#-docker-composeyml-examples) for details)
### Container restarts / crashes
* Check the logs for details. Often a required setting for a notification method is missing.
### unable to resolve host
* Check that your `SCAN_SUBNETS` variable is using the correct mask and `--interface`. See the [subnets docs for details](./SUBNETS.md).
### Invalid JSON
Check the [Invalid JSON errors debug help](./DEBUG_INVALID_JSON.md) docs on how to proceed.
### sudo execution failing (e.g.: on arpscan) on a Raspberry Pi 4
> sudo: unexpected child termination condition: 0
Resolution based on [this issue](https://github.com/linuxserver/docker-papermerge/issues/4#issuecomment-1003657581)
```
wget ftp.us.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.3-2_armhf.deb
sudo dpkg -i libseccomp2_2.5.3-2_armhf.deb
```
The link above will probably break in time too. Go to https://packages.debian.org/sid/armhf/libseccomp2/download to find the new version number and put that in the url.
### Only Router and own device show up
Make sure that the subnet and interface in `SCAN_SUBNETS` are correct. If your device/NAS has multiple ethernet ports, you probably need to change `eth0` to something else.
### Losing my settings and devices after an update
If you lose your devices and/or settings after an update that means you don't have the `/app/db` and `/app/config` folders mapped to a permanent storage. That means every time you update these folders are re-created. Make sure you have the [volumes specified correctly](./DOCKER_COMPOSE.md) in your `docker-compose.yml` or run command.
### The application is slow
Slowness is usually caused by incorrect settings (the app might restart, so check the `app.log`), too many background processes (disable unnecessary scanners), too long scans (limit the number of scanned devices), too many disk operations, or some maintenance plugins might have failed. See the [Performance tips](./PERFORMANCE.md) docs for details.

View File

@@ -1,10 +1,10 @@
# Custom Properties for Devices
![Custom Properties](/docs/img/CUSTOM_PROPERTIES/Device_Custom_Properties.png)
![Custom Properties](./img/CUSTOM_PROPERTIES/Device_Custom_Properties.png)
## Overview
This functionality allows you to define **custom properties** for devices, which can store and display additional information on the device listing page. By marking properties as visible, you can enhance the user interface with quick actions, notes, or external links.
This functionality allows you to define **custom properties** for devices, which can store and display additional information on the device listing page. By marking properties as "Show", you can enhance the user interface with quick actions, notes, or external links.
### Key Features:
- **Customizable Properties**: Define specific properties for each device.
@@ -41,7 +41,7 @@ Custom properties are structured as a list of objects, where each property inclu
## Usage on the Device Listing Page
![Custom Properties](/docs/img/CUSTOM_PROPERTIES/Device_Custom_Properties_vid.gif)
![Custom Properties](./img/CUSTOM_PROPERTIES/Device_Custom_Properties_vid.gif)
Visible properties (`CUSTPROP_show: true`) are displayed as interactive icons in the device listing. Each icon can perform one of the following actions based on the `CUSTPROP_type`:
@@ -63,10 +63,10 @@ Visible properties (`CUSTPROP_show: true`) are displayed as interactive icons in
---
## Example Scenarios
## Example Use Cases
1. **Device Documentation Link**:
- Add a custom property with `CUSTPROP_type` set to `link` or `link_new_tab` to allow quick navigation to the documentation.
- Add a custom property with `CUSTPROP_type` set to `link` or `link_new_tab` to allow quick navigation to the external documentation of the device.
2. **Firmware Details**:
- Use `CUSTPROP_type: show_notes` to display firmware versions or upgrade instructions in a modal.

View File

@@ -1,11 +1,53 @@
# A high-level description of the database structure
⚠ Disclaimer: As I'm not the original author, some of the information might be inaccurate. Feel free to submit a PR to correct anything within this page or documentation in general.
An overview of the most important database tables as well as an detailed overview of the Devices table. The MAC address is used as a foreign key in most cases.
The MAC address is used as a foreign key in most cases.
## Devices database table
## 🔍Tables overview
| Field Name | Description | Sample Value |
|-------------------------|-------------|--------------|
| `devMac` | MAC address of the device. | `00:1A:2B:3C:4D:5E` |
| `devName` | Name of the device. | `iPhone 12` |
| `devOwner` | Owner of the device. | `John Doe` |
| `devType` | Type of the device (e.g., phone, laptop, etc.). If set to a network type (e.g., switch), it will become selectable as a Network Parent Node. | `Laptop` |
| `devVendor` | Vendor/manufacturer of the device. | `Apple` |
| `devFavorite` | Whether the device is marked as a favorite. | `1` |
| `devGroup` | Group the device belongs to. | `Home Devices` |
| `devComments` | User comments or notes about the device. | `Used for work purposes` |
| `devFirstConnection` | Timestamp of the device's first connection. | `2025-03-22 12:07:26+11:00` |
| `devLastConnection` | Timestamp of the device's last connection. | `2025-03-22 12:07:26+11:00` |
| `devLastIP` | Last known IP address of the device. | `192.168.1.5` |
| `devStaticIP` | Whether the device has a static IP address. | `0` |
| `devScan` | Whether the device should be scanned. | `1` |
| `devLogEvents` | Whether events related to the device should be logged. | `0` |
| `devAlertEvents` | Whether alerts should be generated for events. | `1` |
| `devAlertDown` | Whether an alert should be sent when the device goes down. | `0` |
| `devSkipRepeated` | Whether to skip repeated alerts for this device. | `1` |
| `devLastNotification` | Timestamp of the last notification sent for this device. | `2025-03-22 12:07:26+11:00` |
| `devPresentLastScan` | Whether the device was present during the last scan. | `1` |
| `devIsNew` | Whether the device is marked as new. | `0` |
| `devLocation` | Physical or logical location of the device. | `Living Room` |
| `devIsArchived` | Whether the device is archived. | `0` |
| `devParentMAC` | MAC address of the parent device (if applicable) to build the [Network Tree](./NETWORK_TREE.md). | `00:1A:2B:3C:4D:5F` |
| `devParentPort` | Port of the parent device to which this device is connected. | `Port 3` |
| `devIcon` | [Icon](./ICONS.md) representing the device. The value is a base64-encoded SVG or Font Awesome HTML tag. | `PHN2ZyB...` |
| `devGUID` | Unique identifier for the device. | `a2f4b5d6-7a8c-9d10-11e1-f12345678901` |
| `devSite` | Site or location where the device is registered. | `Office` |
| `devSSID` | SSID of the Wi-Fi network the device is connected to. | `HomeNetwork` |
| `devSyncHubNode` | The NetAlertX node ID used for synchronization between NetAlertX instances. | `node_1` |
| `devSourcePlugin` | Source plugin that discovered the device. | `ARPSCAN` |
| `devCustomProps` | [Custom properties](./CUSTOM_PROPERTIES.md) related to the device. The value is a base64-encoded JSON object. | `PHN2ZyB...` |
To understand how values of these fields influuence application behavior, such as Notifications or Network topology, see also:
- [Device Management](./DEVICE_MANAGEMENT.md)
- [Network Tree Topology Setup](./NETWORK_TREE.md)
- [Notifications](./NOTIFICATIONS.md)
## Other Tables overview
| Table name | Description | Sample data |
|----------------------|----------------------| ----------------------|
@@ -23,15 +65,15 @@
[screen1]: /docs/img/DATABASE/CurrentScan.png
[screen2]: /docs/img/DATABASE/Devices.png
[screen4]: /docs/img/DATABASE/Events.png
[screen6]: /docs/img/DATABASE/Online_History.png
[screen7]: /docs/img/DATABASE/Parameters.png
[screen10]: /docs/img/DATABASE/Plugins_Events.png
[screen11]: /docs/img/DATABASE/Plugins_History.png
[screen12]: /docs/img/DATABASE/Plugins_Language_Strings.png
[screen13]: /docs/img/DATABASE/Plugins_Objects.png
[screen15]: /docs/img/DATABASE/Sessions.png
[screen16]: /docs/img/DATABASE/Settings.png
[screen1]: ./img/DATABASE/CurrentScan.png
[screen2]: ./img/DATABASE/Devices.png
[screen4]: ./img/DATABASE/Events.png
[screen6]: ./img/DATABASE/Online_History.png
[screen7]: ./img/DATABASE/Parameters.png
[screen10]: ./img/DATABASE/Plugins_Events.png
[screen11]: ./img/DATABASE/Plugins_History.png
[screen12]: ./img/DATABASE/Plugins_Language_Strings.png
[screen13]: ./img/DATABASE/Plugins_Objects.png
[screen15]: ./img/DATABASE/Sessions.png
[screen16]: ./img/DATABASE/Settings.png

View File

@@ -4,12 +4,12 @@
If a Plugin supplies data to the main app it's doine either vie a SQL query or via a script that updates the `last_result.log` file in the plugin folder (`front/plugins/<plugin>`).
For a more in-depth overview on how plugins work check the [Plugins development docs](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md).
For a more in-depth overview on how plugins work check the [Plugins development docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md).
### Prerequisites
- Make sure you read and followed the specific plugin setup instructions.
- Ensure you have [debug enabled (see More Logging)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md#1-more-logging-)
- Ensure you have [debug enabled (see More Logging)](./DEBUG_TIPS.md)
### Potential issues
@@ -75,7 +75,7 @@ In the above output notice the section logging how many events are produced by t
These values, if formatted correctly, will also show up in the UI:
![Plugins table](/docs/img/DEBUG_PLUGINS/plugin_objects_pihole.png)
![Plugins table](./img/DEBUG_PLUGINS/plugin_objects_pihole.png)
### Sharing application state

View File

@@ -2,14 +2,13 @@
Please follow tips 1 - 4 to get a more detailed error.
## 1. More Logging 📃
## 1. More Logging
When debugging an issue always set the highest log level:
`LOG_LEVEL='trace'`
## 2. Surfacing errors when container restarts 🔁
## 2. Surfacing errors when container restarts
Start the container via the **terminal** with a command similar to this one:
@@ -19,23 +18,23 @@ docker run --rm --network=host \
-v local/path/netalertx/db:/app/db \
-e TZ=Europe/Berlin \
-e PORT=20211 \
jokobsk/netalertx:latest
ghcr.io/jokob-sk/netalertx:latest
```
> ⚠ Please note, don't use the `-d` parameter so you see the error when the container crashes. Use this error in your issue description.
## 3. Check the _dev image and open issues
## 3. Check the _dev image and open issues
If possible, check if your issue got fixed in the `_dev` image before opening a new issue. The container is:
`jokobsk/netalertx-dev:latest`
`ghcr.io/jokob-sk/netalertx-dev:latest`
> ⚠ Please backup your DB and config beforehand!
Please also search [open issues](https://github.com/jokob-sk/NetAlertX/issues).
## 4. Disable restart behavior 🛑
## 4. Disable restart behavior
To prevent a Docker container from automatically restarting in a Docker Compose file, specify the restart policy as `no`:
@@ -60,39 +59,6 @@ Sometimes specific log sections are needed to debug issues. The Devices and Curr
5. Open a new issue and post (redacted) output into the issue description (or send to the netalertx@gmail.com email if sensitive data present).
6. Please set `LOG_LEVEL` to `debug` or lower.
## 📃Common issues
## Common issues
### Permissions
* If facing issues (AJAX errors, can't write to DB, empty screen, etc,) make sure permissions are set correctly, and check the logs under `/app/log`.
* To solve permission issues you can try setting the owner and group of the `app.db` by executing the following on the host system: `docker exec netalertx chown -R www-data:www-data /app/db/app.db`.
* If still facing issues, try to map the app.db file (⚠ not folder) to `:/app/db/app.db` (see [docker-compose Examples](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#-docker-composeyml-examples) for details)
### Container restarts / crashes
* Check the logs for details. Often a required setting for a notification method is missing.
### unable to resolve host
* Check that your `SCAN_SUBNETS` variable is using the correct mask and `--interface`. See teh [subnets docs for details](/docs/SUBNETS.md).
### Invalid JSON
Check the [Invalid JSON errors debug help](/docs/DEBUG_INVALID_JSON.md) docs on how to proceed.
### sudo execution failing (e.g.: on arpscan) on a Raspberry Pi 4
> sudo: unexpected child termination condition: 0
Resolution based on [this issue](https://github.com/linuxserver/docker-papermerge/issues/4#issuecomment-1003657581)
```
wget ftp.us.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.3-2_armhf.deb
sudo dpkg -i libseccomp2_2.5.3-2_armhf.deb
```
The link above will probably break in time too. Go to https://packages.debian.org/sid/armhf/libseccomp2/download to find the new version number and put that in the url.
### Only Router and own device show up
Make sure that the subnet and interface in `SCAN_SUBNETS` are correct. If your device/NAS has multiple ethernet ports, you probably need to change `eth0` to something else.
See [Common issues](./COMMON_ISSUES.md) for details.

View File

@@ -1,14 +1,18 @@
# 🖊 Multi-editing via the UI
# Editing multiple devices at once
NetAlertX allows you to mass-edit devices via a CSV export and import feature, or directly in the UI.
## UI multi edit
> [!NOTE]
> Make sure you have your backups saved and restorable before doing any mass edits. Check [Backup strategies](/docs/BACKUPS.md).
> Make sure you have your backups saved and restorable before doing any mass edits. Check [Backup strategies](./BACKUPS.md).
You can select devices in the _Devices_ view by selecting devices to edit and then clicking the _Multi-edit_ button or via the _Maintenance_ > _Multi-Edit_ section.
![Maintenance > Multi-edit](/docs/img/DEVICES_BULK_EDITING/MULTI-EDIT.gif)
![Maintenance > Multi-edit](./img/DEVICES_BULK_EDITING/MULTI-EDIT.gif)
# 📝Bulk-edit devices via CSV Export/Import
## CSV bulk edit
> [!NOTE]
> As always, backup everything, just in case.
@@ -17,17 +21,19 @@ You can select devices in the _Devices_ view by selecting devices to edit and th
2. A `devices.csv` is generated in the `/config` folder
3. Edit the `devices.csv` file however you like.
![Maintenance > CSV Export](/docs/img/DEVICES_BULK_EDITING/MAINTENANCE_CSV_EXPORT.png)
![Maintenance > CSV Export](./img/DEVICES_BULK_EDITING/MAINTENANCE_CSV_EXPORT.png)
> [!NOTE]
> The file containing a list of Devices including the Network relationships between Network Nodes and connected devices. You can also trigger this by acessing this URL: `<your netalertx url>/php/server/devices.php?action=ExportCSV` or via the `CSV Backup` plugin. (💡 You can schedule this)
![Settings > CSV Backup](/docs/img/DEVICES_BULK_EDITING/CSV_BACKUP_SETTINGS.png)
![Settings > CSV Backup](./img/DEVICES_BULK_EDITING/CSV_BACKUP_SETTINGS.png)
### File encoding format
> [!NOTE]
> Keep Linux line endings (suggested editors: Nano, Notepad++)
![Nodepad++ line endings](/docs/img/DEVICES_BULK_EDITING/NOTEPAD++.png)
![Nodepad++ line endings](./img/DEVICES_BULK_EDITING/NOTEPAD++.png)

View File

@@ -3,4 +3,4 @@
This set of settings allows you to group Devices under different views. The Archived toggle allows you to exclude a Device from most listings and notifications.
![Display settings](/docs/img/DEVICE_MANAGEMENT/DeviceDetails_DisplaySettings.png)
![Display settings](./img/DEVICE_MANAGEMENT/DeviceDetails_DisplaySettings.png)

View File

@@ -4,20 +4,20 @@ The Main Info section is where most of the device identifiable information is st
> [!NOTE]
>
> You can multi-edit devices by selecting them in the main Devices view, from the Mainetence section, or via the CSV Export functionality under Maintenance. More info can be found in the [Devices Bulk-editing docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md).
> You can multi-edit devices by selecting them in the main Devices view, from the Mainetence section, or via the CSV Export functionality under Maintenance. More info can be found in the [Devices Bulk-editing docs](./DEVICES_BULK_EDITING.md).
![Main Info](/docs/img/DEVICE_MANAGEMENT/DeviceManagement_MainInfo.png)
![Main Info](./img/DEVICE_MANAGEMENT/DeviceManagement_MainInfo.png)
## Main Info
- **MAC**: MAC addres of the device. Not editable, unless creating a new dummy device.
- **Last IP**: IP addres of the device. Not editable, unless creating a new dummy device.
- **Name**: Friendly device name. Autodetected via various 🆎 Name discovery [plugins](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md). The app attaches `(IP match)` if the name is discovered via an IP match and not MAC match which could mean the name could be incorrect as IPs might change.
- **Icon**: Partially autodetected. Select an existing or [add a custom icon](https://github.com/jokob-sk/NetAlertX/blob/main/docs/ICONS.md). You can also auto-apply the same icon on all devices of the same type.
- **Name**: Friendly device name. Autodetected via various 🆎 Name discovery [plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md). The app attaches `(IP match)` if the name is discovered via an IP match and not MAC match which could mean the name could be incorrect as IPs might change.
- **Icon**: Partially autodetected. Select an existing or [add a custom icon](./ICONS.md). You can also auto-apply the same icon on all devices of the same type.
- **Owner**: Device owner (The list is self-populated with existing owners and you can add custom values).
- **Type**: Select a device type from the dropdown list (`Smartphone`, `Tablet`,
`Laptop`, `TV`, `router`, etc.) or add a new device type. If you want the device to act as a **Network device** (and be able to be a network node in the Network view), select a type under Network Devices or add a new Network Device type in Settings. More information can be found in the [Network Setup docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md).
`Laptop`, `TV`, `router`, etc.) or add a new device type. If you want the device to act as a **Network device** (and be able to be a network node in the Network view), select a type under Network Devices or add a new Network Device type in Settings. More information can be found in the [Network Setup docs](./NETWORK_TREE.md).
- **Vendor**: The manufacturing vendor. Automatically updated by NetAlertX when empty or unknown, can be edited.
- **Group**: Select a group (`Always on`, `Personal`, `Friends`, etc.) or type
your own Group name.
@@ -32,11 +32,11 @@ The Main Info section is where most of the device identifiable information is st
You can create dummy devices from the Devices listing screen.
![Create Dummy Device](/docs/img/DEVICE_MANAGEMENT/Devices_CreateDummyDevice.png)
![Create Dummy Device](./img/DEVICE_MANAGEMENT/Devices_CreateDummyDevice.png)
The **MAC** field and the **Last IP** field will then become editable.
![Save Dummy Device](/docs/img/DEVICE_MANAGEMENT/DeviceEdit_SaveDummyDevice.png)
![Save Dummy Device](./img/DEVICE_MANAGEMENT/DeviceEdit_SaveDummyDevice.png)
> [!NOTE]

View File

@@ -1,14 +1,38 @@
## Development environment set up
# Development environment set up
>[!NOTE]
> Replace `/development` with the path where your code files will be stored. The default container name is `netalertx` so there might be a conflict with your running containers.
## 1. Download the code:
## Development Guidelines
Before starting development, please scan the below development guidelines.
### Priority Order (Highest to Lowest)
1. 🔼 Fixing core bugs that lack workarounds.
2. 🔵 Adding core functionality that unlocks other features (e.g., plugins).
3. 🔵 Refactoring to enable faster development.
4. 🔽 UI improvements (PRs welcome).
### Design Philosophy
Focus on core functionality and integrate with existing tools rather than reinventing the wheel.
Examples:
- Using **Apprise** for notifications instead of implementing multiple separate gateways.
- Implementing **regex-based validation** instead of one-off validation for each setting.
> [!NOTE]
> UI changes have lower priority, however, PRs are welcome, but **keep them small & focused**.
## Development Environment Set Up
### 1. Download the code:
- `mkdir /development`
- `cd /development && git clone https://github.com/jokob-sk/NetAlertX.git`
## 2. Create a DEV .env_dev file
### 2. Create a DEV .env_dev file
`touch /development/.env_dev && sudo nano /development/.env_dev`
@@ -22,10 +46,12 @@ TZ=Europe/Berlin
PORT=22222 # make sure this port is unique on your whole network
DEV_LOCATION=/development/NetAlertX
APP_DATA_LOCATION=/volume/docker_appdata
# Make sure your GRAPHQL_PORT setting has a port that is unique on your whole host network
APP_CONF_OVERRIDE={"GRAPHQL_PORT":"22223"}
# ALWAYS_FRESH_INSTALL=true # uncommenting this will always delete the content of /config and /db dirs on boot to simulate a fresh install
```
## 3. Create /db and /config dirs
### 3. Create /db and /config dirs
Create a folder `netalertx` in the `APP_DATA_LOCATION` (in this example in `/volume/docker_appdata`) with 2 subfolders `db` and `config`.
@@ -33,7 +59,7 @@ Create a folder `netalertx` in the `APP_DATA_LOCATION` (in this example in `/vol
- `mkdir /volume/docker_appdata/netalertx/db`
- `mkdir /volume/docker_appdata/netalertx/config`
## 4. Run the container
### 4. Run the container
- `cd /development/NetAlertX && sudo docker-compose --env-file ../.env_dev `
@@ -42,7 +68,7 @@ You can then modify the python script without restarting/rebuilding the containe
![image](https://github.com/jokob-sk/NetAlertX/assets/96159884/3cbf2748-03c8-49e7-b801-f38c7755246b)
## 💡 Tips
## Tips
A quick cheat sheet of useful commands.
@@ -54,17 +80,42 @@ A command to stop, remove the container and the image (replace `netalertx` and `
### Restart the server backend
Most code changes can be tetsed without rebuilding the container. When working on the python server backend, you only need to restart the server.
Most code changes can be tested without rebuilding the container. When working on the python server backend, you only need to restart the server.
1. You can usually restart the backend via Maintenance > Logs > Restart server
1. You can usually restart the backend via _Maintenance > Logs > Restart_ server
![image](/docs/img/DEV_ENV_SETUP/Maintenance_Logs_Restart_server.png)
![image](./img/DEV_ENV_SETUP/Maintenance_Logs_Restart_server.png)
2. If above doesn't work, SSH into the container and kill & restart the main script loop
- `sudo docker exec -it netalertx /bin/bash`
- `pkill -f "python /app/server" && python /app/server & `
3. If none of the above work, restart the docker image. This is usually the last resort as sometimes the Docker engine becomes unresponsive and the whole engine needs to be restarted.
3. If none of the above work, restart the docker caontainer.
- This is usually the last resort as sometimes the Docker engine becomes unresponsive and the whole engine needs to be restarted.
## Contributing & Pull Requests
### Before submitting a PR, please ensure:
✔ Changes are **backward-compatible** with existing installs.
✔ No unnecessary changes are made.
✔ New features are **reusable**, not narrowly scoped.
✔ Features are implemented via **plugins** if possible.
### Mandatory Test Cases
- Fresh install (no DB/config).
- Existing DB/config compatibility.
- Notification testing:
- Email
- Apprise (e.g., Telegram)
- Webhook (e.g., Discord)
- MQTT (e.g., Home Assistant)
- Updating Settings and their persistence.
- Updating a Device
- Plugin functionality.
- Error log inspection.

View File

@@ -1,5 +1,8 @@
# `docker-compose.yaml` Examples
> [!NOTE]
> The container needs to run in `network_mode:"host"`.
### Example 1
```yaml
@@ -7,8 +10,8 @@ services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
@@ -33,13 +36,14 @@ To run the container execute: `sudo docker-compose up -d`
Example by [SeimuS](https://github.com/SeimusS).
```yaml
services:
netalertx:
container_name: NetAlertX
hostname: NetAlertX
privileged: true
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: jokobsk/netalertx:latest
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: ghcr.io/jokob-sk/netalertx:latest
environment:
- TZ=Europe/Bratislava
restart: always
@@ -60,8 +64,8 @@ services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
@@ -100,29 +104,41 @@ DEV_LOCATION=/path/to/local/source/code
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
### Example 4
Courtesy of [pbek](https://github.com/pbek). The volume `netalertx_db` is used by the db directory. The two config files are mounted directly from a local folder to their places in the config folder. You can backup the `docker-compose.yaml` folder and the docker volumes folder.
### Example 4: Docker swarm
Notice how the host network is defined in a swarm setup:
```yaml
services:
netalertx:
# use the below line if you want to test the latest dev image
# Use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: jokobsk/netalertx
ports:
- "80:20211/tcp"
environment:
- TZ=Europe/Vienna
networks:
local:
ipv4_address: 192.168.1.2
restart: unless-stopped
image: "ghcr.io/jokob-sk/netalertx:latest"
volumes:
- netalertx_db:/app/db
- ./netalertx/:/app/config/
# (API: OPTION 1) use for performance
- type: tmpfs
target: /app/api
# (API: OPTION 2) use when debugging issues
# - local/path/api:/app/api
- /mnt/MYSERVER/netalertx/config:/config:rw
- /mnt/MYSERVER/netalertx/db:/netalertx/db:rw
- /mnt/MYSERVER/netalertx/logs:/netalertx/front/log:rw
environment:
- TZ=Europe/London
- PORT=20211
# network_mode: host
networks:
- outside
deploy:
mode: replicated
replicas: 1
restart_policy:
condition: on-failure
# placement: # ✅ Placement is now correctly inside deploy
# constraints:
# - node.role == manager
# - node.labels.device == NUC2
networks:
outside:
external:
name: "host"
```

View File

@@ -5,37 +5,19 @@
> ```
> docker run -d --rm --network=host \
> -e TZ=Europe/Berlin \
> -e PUID=200 -e PGID=200 \
> -e PORT=20211 \
> jokobsk/netalertx:latest
> ghcr.io/jokob-sk/netalertx:latest
> ```
NetAlertX runs on an Nginx web server. On Alpine Linux, Nginx operates as the `nginx` user (user ID 101, group ID 82 - `www-data`). Consequently, files accessed or written by the NetAlertX application are owned by `nginx:www-data`.
NetAlertX runs on an Nginx web server. On Alpine Linux, Nginx operates as the `nginx` user (if PUID and GID environment variables are not specified, nginx user UID will be set to 102, and its supplementary group `www-data` ID to 82). Consequently, files accessed or written by the NetAlertX application are owned by `nginx:www-data`.
Upon starting, NetAlertX changes the ownership of files on the host system mapped to `/app/config` and `/app/db` in the container to `nginx:www-data`. This ensures that Nginx can access and write to these files. Since the user in the Docker container is mapped to a user on the host system by ID:GID, the files in `/app/config` and `/app/db` on the host system are owned by a user with the same ID and GID (ID 101 and GID 82). On different systems, this ID:GID may belong to different users (on Debian, the user with ID 82 is `uuidd`), or there may not be a user with ID 82 at all.
Upon starting, NetAlertX changes nginx user UID and www-data GID to specified values (or defaults), and the ownership of files on the host system mapped to `/app/config` and `/app/db` in the container to `nginx:www-data`. This ensures that Nginx can access and write to these files. Since the user in the Docker container is mapped to a user on the host system by ID:GID, the files in `/app/config` and `/app/db` on the host system are owned by a user with the same ID and GID (defaults are ID 102 and GID 82). On different systems, this ID:GID may belong to different users, or there may not be a group with ID 82 at all.
While this generally isn't problematic, it can cause issues for host system users needing to access these files (e.g., backup scripts). If users other than root need access to these files, it is recommended to add those users to the group with GID 82. If that group doesn't exist, it should be created.
Option to set specific user UID and GID can be useful for host system users needing to access these files (e.g., backup scripts).
### Permissions Table for Individual Folders
| Folder | User | User ID | Group | Group ID | Permissions | Notes |
|----------------|--------|---------|-----------|----------|-------------|---------------------------------------------------------------------|
| `/app/config` | nginx | 101 | www-data | 82 | rwxr-xr-x | Ensure `nginx` can read/write; other users can read if in `www-data` |
| `/app/db` | nginx | 101 | www-data | 82 | rwxr-xr-x | Same as above |
### Steps to Add Users to Group
1. **Check if group exists:**
```sh
getent group www-data
```
2. **Create group if it does not exist:**
```sh
sudo groupadd -g 82 www-data
```
3. **Add user to group:**
```sh
sudo usermod -aG www-data <username>
```
Replace `<username>` with the actual username that requires access.
| `/app/config` | nginx | PUID (default 102) | www-data | PGID (default 82) | rwxr-xr-x | Ensure `nginx` can read/write; other users can read if in `www-data` |
| `/app/db` | nginx | PUID (default 102) | www-data | PGID (default 82) | rwxr-xr-x | Same as above |

View File

@@ -1,4 +1,4 @@
# 🖼 Frontend development
# Frontend development
This page contains tips for frontend development when extending NetAlertX. Guiding principles are:

21
docs/HELPER_SCRIPTS.md Executable file
View File

@@ -0,0 +1,21 @@
# NetAlertX Community Helper Scripts Overview
This page provides an overview of community-contributed scripts for NetAlertX. These scripts are not actively maintained and are provided as-is.
## Community Scripts
You can find all scripts in this [scripts GitHub folder](https://github.com/jokob-sk/NetAlertX/tree/main/scripts).
| Script Name | Description | Author | Version | Release Date |
|------------|-------------|--------|---------|--------------|
| **New Devices Checkmk Script** | Checks for new devices in NetAlertX and reports status to Checkmk. | N/A | 1.0 | 08-Jan-2025 |
| **DB Cleanup Script** | Queries and removes old device-related entries from the database. | [laxduke](https://github.com/laxduke) | 1.0 | 23-Dec-2024 |
| **OPNsense DHCP Lease Converter** | Retrieves DHCP lease data from OPNsense and converts it to `dnsmasq` format. | [im-redactd](https://github.com/im-redactd) | 1.0 | 24-Feb-2025 |
## Important Notes
> [!NOTE]
> These scripts are community-supplied and not actively maintained. Use at your own discretion.
For detailed usage instructions, refer to each script's documentation in each [scripts GitHub folder](https://github.com/jokob-sk/NetAlertX/tree/main/scripts).

View File

@@ -3,7 +3,7 @@
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.
> [!TIP]
> You can install NetAlertX also as a Home Assistant addon [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](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/).
> You can install NetAlertX also as a Home Assistant addon [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](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/). 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.
## ⚠ Note
@@ -21,15 +21,18 @@ NetAlertX comes with MQTT support, allowing you to show all detected devices as
2. Configure a user name and password on your broker.
3. Note down the following details that you will need to configure NetAlertX:
- MQTT host url (usually your Home Assistant IP)
- MQTT broker port
- User
- Password
4. Open the _NetAlertX_ > _Settings_ > _MQTT_ settings group
- Enable MQTT
- Fill in the details from above
- Fill in remaining settings as per description
- set MQTT_RUN to schedule or on_notification depending on requirements
![Configuration Example][configuration]
@@ -40,9 +43,50 @@ NetAlertX comes with MQTT support, allowing you to show all detected devices as
| ![Screen 3][list] | ![Screen 4][overview] |
[configuration]: /docs/img/HOME_ASISSTANT/HomeAssistant-Configuration.png "configuration"
[sensors]: /docs/img/HOME_ASISSTANT/HomeAssistant-Device-as-Sensors.png "sensors"
[history]: /docs/img/HOME_ASISSTANT/HomeAssistant-Device-Presence-History.png "history"
[list]: /docs/img/HOME_ASISSTANT/HomeAssistant-Devices-List.png "list"
[overview]: /docs/img/HOME_ASISSTANT/HomeAssistant-Overview-Card.png "overview"
[configuration]: ./img/HOME_ASISSTANT/HomeAssistant-Configuration.png "configuration"
[sensors]: ./img/HOME_ASISSTANT/HomeAssistant-Device-as-Sensors.png "sensors"
[history]: ./img/HOME_ASISSTANT/HomeAssistant-Device-Presence-History.png "history"
[list]: ./img/HOME_ASISSTANT/HomeAssistant-Devices-List.png "list"
[overview]: ./img/HOME_ASISSTANT/HomeAssistant-Overview-Card.png "overview"
## Troubleshooting
If you can't see all devices detected, run `sudo arp-scan --interface=eth0 192.168.1.0/24` (change these based on your setup, read [Subnets](./SUBNETS.md) docs for details). This command has to be executed the NetAlertX container, not in the Home Assistant container.
You can access the NetAlertX container via Portainer on your host or via ssh. The container name will be something like `addon_db21ed7f_netalertx` (you can copy the `db21ed7f_netalertx` part from the browser when accessing the UI of NetAlertX).
## Accessing the NetAlertX container via SSH
1. Log into your Home Assistant host via SSH
```bash
local@local:~ $ ssh pi@192.168.1.9
```
2. Find the NetAlertX container name, in this case `addon_db21ed7f_netalertx`
```bash
pi@raspberrypi:~ $ sudo docker container ls | grep netalertx
06c540d97f67 ghcr.io/alexbelgium/netalertx-armv7:25.3.1 "/init" 6 days ago Up 6 days (healthy) addon_db21ed7f_netalertx
```
3. SSH into the NetAlertX cointainer
```bash
pi@raspberrypi:~ $ sudo docker exec -it addon_db21ed7f_netalertx /bin/sh
/ #
```
4. Execute a test `asrp-scan` scan
```bash
/ # sudo arp-scan --ignoredups --retry=6 192.168.1.0/24 --interface=eth0
Interface: eth0, type: EN10MB, MAC: dc:a6:32:73:8a:b1, IPv4: 192.168.1.9
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.1.1 74:ac:b9:54:09:fb Ubiquiti Networks Inc.
192.168.1.21 74:ac:b9:ad:c3:30 Ubiquiti Networks Inc.
192.168.1.58 1c:69:7a:a2:34:7b EliteGroup Computer Systems Co., LTD
192.168.1.57 f4:92:bf:a3:f3:56 Ubiquiti Networks Inc.
...
```
If your result doesn't contain results similar to the above, double check your subnet, interface and if you are dealing with an inaccessible network segment, read the [Remote networks documentation](./REMOTE_NETWORKS.md).

View File

@@ -1,8 +1,8 @@
## Icons overview
Icons are used to visually distinguish devices in the app in most of the device listing tables and the [network tree](/docs/NETWORK_TREE.md).
Icons are used to visually distinguish devices in the app in most of the device listing tables and the [network tree](./NETWORK_TREE.md).
![Raspberry Pi with a brand icon](/docs/img/ICONS/devices-icons.png)
![Raspberry Pi with a brand icon](./img/ICONS/devices-icons.png)
### Icons Support
@@ -19,19 +19,19 @@ You can assign icons individually on each device in the Details tab.
Copying the SVG (for example from [iconify.design](https://icon-sets.iconify.design/)):
![iconify svg](/docs/img/ICONS/iconify_design_copy_svg.png)
![iconify svg](./img/ICONS/iconify_design_copy_svg.png)
Copying the HTML code from [Font Awesome](https://fontawesome.com/search?o=r&m=free).
![Font awesome](/docs/img/ICONS/font_awesome_copy_html.png)
![Font awesome](./img/ICONS/font_awesome_copy_html.png)
2. Navigate to the device you want to use the icon on and click the "+" icon:
![preview](/docs/img/ICONS/device_add_icon.png)
![preview](./img/ICONS/device_add_icon.png)
3. Paste in the copied HTML or SVG code and click "OK":
![Paste SVG](/docs/img/ICONS/paste-svg.png)
![Paste SVG](./img/ICONS/paste-svg.png)
6. "Save" the device
@@ -40,7 +40,7 @@ Copying the HTML code from [Font Awesome](https://fontawesome.com/search?o=r&m=f
- The dropdown contains all icons already used in the app for device icons. You might need to navigate away or refresh the page once you add a new icon.
## 🌟 Pro Font Awesome icons
## Font Awesome Pro icons
If you own the premium package of Font Awesome icons you can mount it in your Docker container the following way:

42
docs/INITIAL_SETUP.md Executable file
View File

@@ -0,0 +1,42 @@
# ⚙ Initial Setup
## 📁 Configuration Files
- On first run, the app generates a default `app.conf` and `app.db` if unavailable.
- Preferred method: Use the **Settings UI**.
- If the UI is inaccessible, manually edit [`app.conf`](https://github.com/jokob-sk/NetAlertX/tree/main/back) in `/app/config/`.
---
## 🖥️ Setting Up Scanners
- Define networks to scan by entering accessible subnets.
- Default plugin: **ARPSCAN** → Requires at least one valid subnet + interface in `SCAN_SUBNETS`.
- 📖 [Subnet & VLAN setup guide](./SUBNETS.md) (for troubleshooting and advanced scenarios).
### 🔄 PiHole Sync
- If using **PiHole**, devices can be synced automatically.
- 📖 [PiHole configuration guide](./PIHOLE_GUIDE.md).
### 📦 Bulk Import
> [!NOTE]
> You can bulk-import devices via the [CSV import method](./DEVICES_BULK_EDITING.md).
---
## 🌍 Community Guides
- Various community-written configuration guides in **Chinese, Korean, German, French**.
- 📖 [Community Guides](./COMMUNITY_GUIDES.md)
> ⚠️ **Note:** These guides may be outdated. Always refer to the official documentation first.
---
## 🛠️ Common Issues
Before creating a new issue:
- Check if a similar issue was [already resolved](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed).
- Review [common debugging tips](./DEBUG_TIPS.md).
- Check [Common Issues](./COMMON_ISSUES.md)

25
docs/INSTALLATION.md Executable file
View File

@@ -0,0 +1,25 @@
# Installation
## Installation options
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised the Home Assistant instance, as an Unraid app and lastly on bare metal.
- [[Installation] Docker (recommended)](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
- [[Installation] Unraid App](https://unraid.net/community/apps)
- [[Installation] Bare metal (experimental - looking for maintainers)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md)
## Help
If facing issues, please spend a few minutes seraching.
- Check [common issues](./COMMON_ISSUES.md)
- Have a look at [Community guides](./COMMUNITY_GUIDES.md)
- [Search closed or open issues or discussions](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue)
- Check [Discord](https://discord.gg/NczTUTWyRr)
> [!NOTE]
> If you can't find a solution anywhere, ask in Discord if you think it's a quick question, otherwise open a new [issue](https://github.com/jokob-sk/NetAlertX/issues/new?template=setup-help.yml). Please fill in as much as possible to speed up the help process.
>

View File

@@ -6,7 +6,7 @@
## STEPS:
> [!TIP]
> In short: The application will auto-migrate the database, config, and all device information. A ticker message on top will be displayed until you update your docker mount points. It's always good to have a [backup strategy](https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md) in place.
> In short: The application will auto-migrate the database, config, and all device information. A ticker message on top will be displayed until you update your docker mount points. It's always good to have a [backup strategy](./BACKUPS.md) in place.
1. Backup your current config and database (optional `devices.csv` to have a backup) (See bellow tip if facing issues)
2. Stop the container
@@ -38,24 +38,23 @@ The application installation folder in the docker container has changed from `/h
> [!NOTE]
> The application uses symlinks linking the old db and config locations to the new ones, so data loss should not occur. [Backup strategies](https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md) are still recommended to backup your setup.
> The application uses symlinks linking the old db and config locations to the new ones, so data loss should not occur. [Backup strategies](./BACKUPS.md) are still recommended to backup your setup.
# Examples
Exmaples of docker files with the new mount points.
Examples of docker files with the new mount points.
## Example 1: Mapping folders
### Old docker-compose.yml
```yaml
version: "3"
services:
pialert:
container_name: pialert
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "jokobsk/pialert:latest"
network_mode: "host"
restart: unless-stopped
@@ -72,13 +71,12 @@ services:
### New docker-compose.yml
```yaml
version: "3"
services:
netalertx: # ⚠ This has changed (🟡optional)
container_name: netalertx # ⚠ This has changed (🟡optional)
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
network_mode: "host"
restart: unless-stopped
volumes:
@@ -100,12 +98,11 @@ services:
### Old docker-compose.yml
```yaml
version: "3"
services:
pialert:
container_name: pialert
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "jokobsk/pialert:latest"
network_mode: "host"
restart: unless-stopped
@@ -122,13 +119,12 @@ services:
### New docker-compose.yml
```yaml
version: "3"
services:
netalertx: # ⚠ This has changed (🟡optional)
container_name: netalertx # ⚠ This has changed (🟡optional)
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
network_mode: "host"
restart: unless-stopped
volumes:

View File

@@ -2,7 +2,7 @@
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node) set to a network device type (e.g.: **Type**:`Router`).
> 💡 Tip: You can add dummy devices via the [Create dummy device](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICE_MANAGEMENT.md#dummy-devices) button in the Devices listing page.
> 💡 Tip: You can add dummy devices via the [Create dummy device](./DEVICE_MANAGEMENT.md#dummy-devices) button in the Devices listing page.
> 💡 Tip: Export your configuration of the Network and Devices once in a while via the Export CSV feature under **Maintenance** -> **Backup/Restore** -> **CSV Export**.
@@ -17,7 +17,7 @@ Make sure you have a root device with the MAC `Internet` (No other MAC addresses
> [!NOTE]
>
> [Bulk-edit devices](/docs/DEVICES_BULK_EDITING.md) by using the _CSV Export_ functionality in the _Maintenance_ section. You can use this to fix `Internet` node assignment issues.
> [Bulk-edit devices](./DEVICES_BULK_EDITING.md) by using the _CSV Export_ functionality in the _Maintenance_ section. You can use this to fix `Internet` node assignment issues.
## 🔍Detailed example:
@@ -27,7 +27,7 @@ In this example you will setup a device named `rapberrypi` as a `Switch` in our
- Go to the `Devices` (1) page:
![Device details](/docs/img/NETWORK_TREE/Device_Details_Network_Type.png)
![Device details](./img/NETWORK_TREE/Device_Details_Network_Type.png)
- In the (2) `Details` tab navigate to the the `Type` (3) dropdown and select the type `Switch` (4).
@@ -42,7 +42,7 @@ In this example you will setup a device named `rapberrypi` as a `Switch` in our
- Navigate to your `Network` (1) page:
![Network page](/docs/img/NETWORK_TREE/Network_Page.png)
![Network page](./img/NETWORK_TREE/Network_Page.png)
- Notice the newly added `raspberrypi` (2) tab which now represents a network node, also showing up in the tree (3).
- As we asssigned the `raspberrypi` in the previous (1) Device details page section to the `Internet` parent network node in step (6), the link is also showing up in the tree diagram (4)
@@ -52,7 +52,7 @@ In this example you will setup a device named `rapberrypi` as a `Switch` in our
- After clicking the `Assign` button in the previous section, the `(AppleTV)` (1) device is now connected to our `raspberrypi` (2).
![Network page with 2 levels](/docs/img/NETWORK_TREE/Network_Page_2_Levels.png)
![Network page with 2 levels](./img/NETWORK_TREE/Network_Page_2_Levels.png)
- You can see the `raspberrypi` represents the Network node type `Switch` (3)
- The `(AppleTV)` to `raspberrypi` connection is also displayed in the table of `Connected devices` (4).

View File

@@ -9,21 +9,24 @@ There are 4 ways how to influence notifications:
> [!NOTE]
> It's recommended to use the same schedule interval for all plugins responsible for scanning devices, otherwise false positives might be reported if different devices are discovered by different plugins. Check the **Settings** > **Enabled settings** section for a warning:
> ![Schedules out-of-sync](/docs/img/NOTIFICATIONS/Schedules_out-of-sync.png)
> ![Schedules out-of-sync](./img/NOTIFICATIONS/Schedules_out-of-sync.png)
## Device settings 💻
![Device notification settings](/docs/img/NOTIFICATIONS/Device-notification-settings.png)
![Device notification settings](./img/NOTIFICATIONS/Device-notification-settings.png)
There are 4 settings on the device for influencing notifications. You can:
1. **Alert Events** - Enables alerts of connections, disconnections, IP changes.
2. **Alert Down** - Alerts when a device goes down. This setting overrides a disabled **Alert Events** setting, so you will get a notification of a device going down even if you don't have **Alert Events** ticked.
1. **Alert Events** - Enables alerts of connections, disconnections, IP changes (down and down reconnected notifications are still sent even if this is disabled).
2. **Alert Down** - Alerts when a device goes down. This setting overrides a disabled **Alert Events** setting, so you will get a notification of a device going down even if you don't have **Alert Events** ticked. Disabling this will disable down and down reconnected notifications on the device.
3. **Skip repeated notifications**, if for example you know there is a temporary issue and want to pause the same notification for this device for a given time.
> [!NOTE]
> Please read through the [NTFPRCS plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/notification_processing/README.md) documentation to understand how device and global settings influence the notification processing.
## Plugin settings 🔌
![Plugin notification settings](/docs/img/NOTIFICATIONS/Plugin-notification-settings.png)
![Plugin notification settings](./img/NOTIFICATIONS/Plugin-notification-settings.png)
On almost all plugins there are 2 core settings, `<plugin>_WATCH` and `<plugin>_REPORT_ON`.
@@ -34,18 +37,18 @@ Click the **Read more in the docs.** Link at the top of each plugin to get more
## Global settings ⚙
![Global notification settings](/docs/img/NOTIFICATIONS/Global-notification-settings.png)
![Global notification settings](./img/NOTIFICATIONS/Global-notification-settings.png)
In Notification Processing settings, you can specify blanket rules. These allow you to specify exceptions to the Plugin and Device settings and will override those.
1. Notify on (`NTFPRCS_INCLUDED_SECTIONS`) allows you to specify which events trigger notifications. Usual setups will have `new_devices`, `down_devices`, and possibly `down_reconnected` set. Including `plugin` (dependenton the Plugin `<plugin>_WATCH` and `<plugin>_REPORT_ON` settings) and `events` (dependent on the on-device **Alert Events** setting) might be too noisy for most setups. More info in the [NTFPRCS plugin](/front/plugins/notification_processing/README.md)
1. Notify on (`NTFPRCS_INCLUDED_SECTIONS`) allows you to specify which events trigger notifications. Usual setups will have `new_devices`, `down_devices`, and possibly `down_reconnected` set. Including `plugin` (dependenton the Plugin `<plugin>_WATCH` and `<plugin>_REPORT_ON` settings) and `events` (dependent on the on-device **Alert Events** setting) might be too noisy for most setups. More info in the [NTFPRCS plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/notification_processing/README.md) on what events these selections include.
2. Alert down after (`NTFPRCS_alert_down_time`) is useful if you want to wait for some time before the system sends out a down notification for a device. This is related to the on-device **Alert down** setting and only devices with this checked will trigger a down notification.
3. A filter to allow you to set device-specific exceptions to New devices being added to the app.
4. A filter to allow you to set device-specific exceptions to generated Events.
## Ignoring devices 🔕
![Ignoring new devices](/docs/img/NOTIFICATIONS/NEWDEV_ignores.png)
![Ignoring new devices](./img/NOTIFICATIONS/NEWDEV_ignores.png)
You can completely ignore detected devices globally. This could be because your instance detects docker containers, you want to ignore devices from a specific manufacturer via MAC rules or you want to ignore devices on a specific IP range.

View File

@@ -1,59 +1,96 @@
# Performance tips
# Performance Optimization Guide
The application runs regular maintenance and DB cleanup tasks. If these tasks fail, you might encounter performance issues.
There are several ways to improve the application's performance. The application has been tested on a range of devices, from a Raspberry Pi 4 to NAS and NUC systems. If you are running the application on a lower-end device, carefully fine-tune the performance settings to ensure an optimal user experience.
Most performance issues are caused by a big database or large log files. Enabling unnecessary plugins will also lead to performance degradation.
## Common Causes of Slowness
You can always check the size of your database and database tables under the Maintenance page.
Performance issues are usually caused by:
![Db size check](/docs/img/PERFORMANCE/db_size_check.png)
- **Incorrect settings** The app may restart unexpectedly. Check `app.log` under **Maintenance → Logs** for details.
- **Too many background processes** Disable unnecessary scanners.
- **Long scan durations** Limit the number of scanned devices.
- **Excessive disk operations** Optimize scanning and logging settings.
- **Failed maintenance plugins** Ensure maintenance tasks are running properly.
The application performs regular maintenance and database cleanup. If these tasks fail, performance may degrade.
### Database and Log File Size
A large database or oversized log files can slow down performance. You can check database and table sizes on the **Maintenance** page.
![DB size check](./img/PERFORMANCE/db_size_check.png)
> [!NOTE]
> For around 100 devices the database should be approximately `50MB` and none of the entries (rows) should exceed the value of `10 000` on a healthy system. These numbers will depend on your network activity and settings.
> - For **~100 devices**, the database should be around **50MB**.
> - No table should exceed **10,000 rows** in a healthy system.
> - These numbers vary based on network activity and settings.
## Maintenance plugins
---
There are 2 plugins responsible for maintaining the overal health of the application. One is responsible for the database cleanup and one for other tasks, such as log cleanup.
## Maintenance Plugins
### DB Cleanup (DBCLNP)
Two plugins help maintain the applications performance:
The database cleanup plugin. Check details and related setting in the [DB Cleanup plugin docs](/front/plugins/db_cleanup/README.md). Make sure the plugin is not failing by checking the logs. Try changing the schedule `DBCLNP_RUN_SCHD` and the timeout `DBCLNP_RUN_TIMEOUT` (increase) if the plugin is failing to execute.
### **1. Database Cleanup (DBCLNP)**
- Responsible for database maintenance.
- Check settings in the [DB Cleanup Plugin Docs](/front/plugins/db_cleanup/README.md).
- Ensure its not failing by checking logs.
- Adjust the schedule (`DBCLNP_RUN_SCHD`) and timeout (`DBCLNP_RUN_TIMEOUT`) if needed.
### Maintenance (MAINT)
### **2. Maintenance (MAINT)**
- Handles log cleanup and other maintenance tasks.
- Check settings in the [Maintenance Plugin Docs](/front/plugins/maintenance/README.md).
- Ensure its running correctly by checking logs.
- Adjust the schedule (`MAINT_RUN_SCHD`) and timeout (`MAINT_RUN_TIMEOUT`) if needed.
The maintenance plugin. Check details and related setting in the [Maintenance plugin docs](/front/plugins/maintenance/README.md). Make sure the plugin is not failing by checking the logs. Try changing the schedule `MAINT_RUN_SCHD` and the timeout `MAINT_RUN_TIMEOUT` (increase) if the plugin is failing to execute.
---
## Scan frequency and coverage
## Scan Frequency and Coverage
The more often you scan the networks the more resources, traffic and DB read/write cycles are executed. Especially on busy networks and lower end hardware, consider increasing scan intervals (`<PLUGIN>_RUN_SCHD`) and timeouts (`<PLUGIN>_RUN_TIMEOUT`).
Frequent scans increase resource usage, network traffic, and database read/write cycles.
Also consider decreasing the scanned subnet, e.g. from `/16` to `/24` if need be.
### **Optimizations**
- **Increase scan intervals** (`<PLUGIN>_RUN_SCHD`) on busy networks or low-end hardware.
- **Extend scan timeouts** (`<PLUGIN>_RUN_TIMEOUT`) to prevent failures.
- **Reduce the subnet size** e.g., from `/16` to `/24` to lower scan loads.
# Store temporary files in memory
Some plugins have additional options to limit the number of scanned devices. If certain plugins take too long to complete, check if you can optimize scan times by selecting a scan range.
For example, the **ICMP plugin** allows you to specify a regular expression to scan only IPs that match a specific pattern.
---
## Storing Temporary Files in Memory
On systems with slower I/O speeds, you can optimize performance by storing temporary files in memory. This primarily applies to the `/app/api` and `/app/log` folders.
Using `tmpfs` reduces disk writes and improves performance. However, it should be **disabled** if persistent logs or API data storage are required.
Below is an optimized `docker-compose.yml` snippet:
You can also store temporary files in application memory (`/app/api` and `/app/log` folders). See highlighted lines `◀` below.
```yaml
version: "3"
services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
# Uncomment the line below to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
# (Optional) Useful for debugging setup issues
- local/path/logs:/app/log
# (API: OPTION 1) use for performance
# (API: OPTION 1) Store temporary files in memory (recommended for performance)
- type: tmpfs # ◀
target: /app/api # ◀
# (API: OPTION 2) use when debugging issues
# (API: OPTION 2) Store API data on disk (useful for debugging)
# - local/path/api:/app/api
environment:
- TZ=Europe/Berlin
- PORT=20211
```

View File

@@ -1,10 +1,10 @@
# Integration with PiHole
NetAlertX comes with 2 plugins suitable for integarting with your existing PiHole instace. One plugin is using a direct SQLite DB connection, the other leverages the DHCP.leases file generated by PiHole. You can combine both approaches and also supplement it with other [plugins](/front/plugins/README.md).
NetAlertX comes with 2 plugins suitable for integarting with your existing PiHole instace. One plugin is using a direct SQLite DB connection, the other leverages the DHCP.leases file generated by PiHole. You can combine both approaches and also supplement it with other [plugins](/docs/PLUGINS.md).
## Approach 1: `DHCPLSS` Plugin - Import devices from the PiHole DHCP leases file
![DHCPLSS sample settings](/docs/img/PIHOLE_GUIDE/DHCPLSS_pihole_settings.png)
![DHCPLSS sample settings](./img/PIHOLE_GUIDE/DHCPLSS_pihole_settings.png)
### Settings
@@ -25,7 +25,7 @@ Check the [DHCPLSS plugin readme](https://github.com/jokob-sk/NetAlertX/tree/mai
## Approach 2: `PIHOLE` Plugin - Import devices directly from the PiHole database
![DHCPLSS sample settings](/docs/img/PIHOLE_GUIDE/PIHOLE_settings.png)
![DHCPLSS sample settings](./img/PIHOLE_GUIDE/PIHOLE_settings.png)
| Setting | Description | Recommended value |
| :------------- | :------------- | :-------------|
@@ -42,4 +42,4 @@ Check the [PiHole plugin readme](https://github.com/jokob-sk/NetAlertX/tree/main
| `:/etc/pihole/pihole-FTL.db` | PiHole's `pihole-FTL.db` database file. |
Check out other [plugins](/front/plugins/README.md) that can help you discover more about your network or check how to scan [Remote networks](/docs/REMOTE_NETWORKS.md).
Check out other [plugins](/docs/PLUGINS.md) that can help you discover more about your network or check how to scan [Remote networks](./REMOTE_NETWORKS.md).

113
docs/PLUGINS.md Executable file
View File

@@ -0,0 +1,113 @@
# 🔌 Plugins
NetAlertX supports additional plugins to extend its functionality, each with its own settings and options. Plugins can be loaded via the General -> `LOADED_PLUGINS` setting. For custom plugin development, refer to the [Plugin development guide](./PLUGINS_DEV.md).
>[!NOTE]
> Please check this [Plugins debugging guide](./DEBUG_PLUGINS.md) and the corresponding Plugin documentation in the below table if you are facing issues.
## ⚡ Quick start
> [!TIP]
> You can load additional Plugins via the General -> `LOADED_PLUGINS` setting.
1. Pick your `🔍 dev scanner` plugin (e.g. `ARPSCAN` or `NMAPDEV`), or import devices into the application with an `📥 importer` plugin. (See **✅Enabling plugins** below)
2. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
3. Setup your [Network topology diagram](./NETWORK_TREE.md)
4. Fine-tune [Notifications](./NOTIFICATIONS.md)
5. [Backup your setup](./BACKUPS.md)
6. Contribute and [Create custom plugins](./PLUGINS_DEV.md)
## 📑 Available Plugins
Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however, it makes sense to have at least some device-detecting plugins enabled, such as `ARPSCAN` or `NMAPDEV`.
| ID | Type | Description | Features | Required | Data source | Detailed docs |
|---------------|---------|--------------------------------------------|----------|----------|--------------|---------------------------------------------------------------------|
| `APPRISE` | ▶️ | Apprise notification proxy | | | Script | [_publisher_apprise](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_apprise/) |
| `ARPSCAN` | 🔍 | ARP-scan on current network | | | Script | [arp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/arp_scan/) |
| `AVAHISCAN` | 🆎 | Avahi (mDNS-based) name resolution | | | Script | [avahi_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/avahi_scan/) |
| `ASUSWRT` | 🔍 | Import connected devices from AsusWRT | | | Script | [asuswrt_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/asuswrt_import/) |
| `CSVBCKP` | ⚙ | CSV devices backup | | | Script | [csv_backup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup/) |
| `CUSTPROP` | ⚙ | Managing custom device properties values | | Yes | Template | [custom_props](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/custom_props/) |
| `DBCLNP` | ⚙ | Database cleanup | | Yes* | Script | [db_cleanup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/db_cleanup/) |
| `DDNS` | ⚙ | DDNS update | | | Script | [ddns_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ddns_update/) |
| `DHCPLSS` | 🔍/📥/🆎| Import devices from DHCP leases | | | Script | [dhcp_leases](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_leases/) |
| `DHCPSRVS` | ♻ | DHCP servers | | | Script | [dhcp_servers](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_servers/) |
| `FREEBOX` | 🔍/♻/🆎| Pull data and names from Freebox/Iliadbox | | | Script | [freebox](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/freebox/) |
| `ICMP` | 🔍 | ICMP (ping) status checker | | | Script | [icmp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/icmp_scan/) |
| `INTRNT` | 🔍 | Internet IP scanner | | | Script | [internet_ip](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_ip/) |
| `INTRSPD` | ♻ | Internet speed test | | | Script | [internet_speedtest](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_speedtest/) |
| `IPNEIGH` | 🔍 | Scan ARP (IPv4) and NDP (IPv6) tables | | | Script | [ipneigh](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ipneigh/) |
| `LUCIRPC` | 🔍 | Import connected devices from OpenWRT | | | Script | [luci_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/luci_import/) |
| `MAINT` | ⚙ | Maintenance of logs, etc. | | | Script | [maintenance](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/maintenance/) |
| `MQTT` | ▶️ | MQTT for synching to Home Assistant | | | Script | [_publisher_mqtt](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_mqtt/) |
| `NBTSCAN` | 🆎 | Nbtscan (NetBIOS-based) name resolution | | | Script | [nbtscan_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nbtscan_scan/) |
| `NEWDEV` | ⚙ | New device template | | Yes | Template | [newdev_template](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/newdev_template/) |
| `NMAP` | ♻ | Nmap port scanning & discovery | | | Script | [nmap_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_scan/) |
| `NMAPDEV` | 🔍 | Nmap dev scan on current network | | | Script | [nmap_dev_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_dev_scan/) |
| `NSLOOKUP` | 🆎 | NSLookup (DNS-based) name resolution | | | Script | [nslookup_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nslookup_scan/) |
| `NTFPRCS` | ⚙ | Notification processing | | Yes | Template | [notification_processing](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/notification_processing/)|
| `NTFY` | ▶️ | NTFY notifications | | | Script | [_publisher_ntfy](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_ntfy/) |
| `OMDSDN` | 📥/🆎 | OMADA TP-Link import | 🖧 🔄 | | Script | [omada_sdn_imp](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_imp/) |
| `OMDSDNOPENAPI`| 📥/🆎 | OMADA TP-Link import via OpenAPI | 🖧 | | Script | [omada_sdn_openapi](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_openapi/) |
| `PIHOLE` | 🔍/🆎/📥| Pi-hole device import & sync | | | SQLite DB | [pihole_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/pihole_scan/) |
| `PUSHSAFER` | ▶️ | Pushsafer notifications | | | Script | [_publisher_pushsafer](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushsafer/) |
| `PUSHOVER` | ▶️ | Pushover notifications | | | Script | [_publisher_pushover](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushover/) |
| `SETPWD` | ⚙ | Set password | | Yes | Template | [set_password](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/set_password/) |
| `SMTP` | ▶️ | Email notifications | | | Script | [_publisher_email](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_email/) |
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | | Script | [snmp_discovery](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/snmp_discovery/) |
| `SYNC` | 🔍/⚙/📥| Sync & import from NetAlertX instances | 🖧 🔄 | Yes | Script | [sync](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/sync/) |
| `TELEGRAM` | ▶️ | Telegram notifications | | | Script | [_publisher_telegram](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_telegram/) |
| `UI` | ♻ | UI specific settings | | Yes | Template | [ui_settings](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ui_settings/) |
| `UNFIMP` | 🔍/📥/🆎| UniFi device import & sync | 🖧 | | Script | [unifi_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/unifi_import/) |
| `VNDRPDT` | ⚙ | Vendor database update | | | Script | [vendor_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/vendor_update/) |
| `WEBHOOK` | ▶️ | Webhook notifications | | | Script | [_publisher_webhook](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_webhook/) |
| `WEBMON` | ♻ | Website down monitoring | | | Script | [website_monitor](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/website_monitor/) |
| `WOL` | ♻ | Automatic wake-on-lan | | | Script | [wake_on_lan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/wake_on_lan/) |
> \* The database cleanup plugin (`DBCLNP`) is not _required_ but the app will become unusable after a while if not executed.
> ❌ marked for removal
> ⌚It's recommended to use the same schedule interval for all plugins responsible for discovering new devices.
## Plugin types
| Plugin type | Icon | Description | When to run | Required | Data source [?](./PLUGINS_DEV.md) |
| -------------- | ---- | ---------------------------------------------------------------- | ----------------------------------- | -------- | ------------------------------------- |
| publisher | ▶️ | Sending notifications to services. | `on_notification` | ✖ | Script |
| dev scanner | 🔍 | Create devices in the app, manages online/offline device status. | `schedule` | ✖ | Script / SQLite DB |
| name discovery | 🆎 | Discovers names of devices via various protocols. | `before_name_updates`, `schedule` | ✖ | Script |
| importer | 📥 | Importing devices from another service. | `schedule` | ✖ | Script / SQLite DB |
| system | ⚙ | Providing core system functionality. | `schedule` / always on | ✖/✔ | Script / Template |
| other | ♻ | Other plugins | misc | ✖ | Script / Template |
## Features
| Icon | Description |
| ---- | ------------------------------------------------------------ |
| 🖧 | Auto-imports the network topology diagram |
| 🔄 | Has the option to sync some data back into the plugin source |
## ✅Enabling plugins
Plugins can be enabled via Settings, and can be disabled as needed.
1. Research which plugin you'd like to use, enable `DISCOVER_PLUGINS` and load the required plugins in Settings via the `LOADED_PLUGINS` setting.
1. Save the changes and review the Settings of the newly loaded plugins.
1. Change the `<prefix>_RUN` Setting to the recommended or custom value as per the documentation of the given setting
- If using `schedule` on a `🔍 dev scanner` plugin, make sure the schedules are the same across all `🔍 dev scanner` plugins
### Disabling, Unloading and Ignoring plugins
1. Change the `<prefix>_RUN` Setting to `disabled` if you want to disable the plugin, but keep the settings
1. If you want to speed up the application, you can unload the plugin by unselecting it in the `LOADED_PLUGINS` setting.
- Careful, once you save the Settings Unloaded plugin settings will be lost (old `app.conf` files are kept in the `/config` folder)
1. You can completely ignore plugins by placing a `ignore_plugin` file into the plugin directory. Ignored plugins won't show up in the `LOADED_PLUGINS` setting.
## 🆕 Developing new custom plugins
If you want to develop a custom plugin, please read this [Plugin development guide](./PLUGINS_DEV.md).

View File

@@ -1,4 +1,4 @@
## 🌟 Create a custom plugin: Overview
# Creating a custom plugin
NetAlertX comes with a plugin system to feed events from third-party scripts into the UI and then send notifications, if desired. The highlighted core functionality this plugin system supports, is:
@@ -13,9 +13,9 @@ NetAlertX comes with a plugin system to feed events from third-party scripts int
### 🎥 Watch the video:
> [!TIP]
> Read this guide [Development environment setup guide](/docs/DEV_ENV_SETUP.md) to set up your local environment for development. 👩‍💻
> Read this guide [Development environment setup guide](./DEV_ENV_SETUP.md) to set up your local environment for development. 👩‍💻
[![Watch the video](/docs/img/YouTube_thumbnail.png)](https://youtu.be/cdbxlwiWhv8)
[![Watch the video](./img/YouTube_thumbnail.png)](https://youtu.be/cdbxlwiWhv8)
### 📸 Screenshots
@@ -126,7 +126,7 @@ You can show or hide the UI on the "Plugins" page and "Plugins" tab for a plugin
If the `data_source` is set to `script` the `CMD` setting (that you specify in the `settings` array section in the `config.json`) contains an executable Linux command, that usually generates a `last_result.<prefix>.log` file (not required if you don't import any data into the app). The `last_result.<prefix>.log` file needs to be saved in `/api/log/plugins`.
> [!IMPORTANT]
> A lot of the work is taken care of by the [`plugin_helper.py` library](/front/plugins/plugin_helper.py). You don't need to manage the `last_result.<prefix>.log` file if using the helper objects. Check other `script.py` of other plugins for details (The [Undicoverables plugins `script.py` file](/front/plugins/undiscoverables/script.py) is a good example).
> A lot of the work is taken care of by the [`plugin_helper.py` library](/front/plugins/plugin_helper.py). You don't need to manage the `last_result.<prefix>.log` file if using the helper objects. Check other `script.py` of other plugins for details.
The content of the `last_result.<prefix>.log` file needs to contain the columns as defined in the "Column order and values" section above. The order of columns can't be changed. After every scan it should contain only the results from the latest scan/execution.
@@ -503,7 +503,7 @@ Below are some general additional notes, when defining `params`:
#### ⚙ Setting object structure
> [!NOTE]
> The settings flow and when Plugin specific settings are applied is described under the [Settings system](/docs/SETTINGS_SYSTEM.md).
> The settings flow and when Plugin specific settings are applied is described under the [Settings system](./SETTINGS_SYSTEM.md).
Required attributes are:
@@ -578,7 +578,7 @@ Each element may also have associated events (e.g., running a scan or triggering
##### Supported settings `function` values
You can have any `"function": "my_custom_name"` custom name, however, the ones listed below have a specific functionality attached to them. If you use a custom name, then the setting is mostly used as an input parameter for the `params` section.
You can have any `"function": "my_custom_name"` custom name, however, the ones listed below have a specific functionality attached to them.
| Setting | Description |
| ------- | ----------- |
@@ -593,7 +593,7 @@ You can have any `"function": "my_custom_name"` custom name, however, the ones l
| | - "before_config_save" - run before the config is marked as saved. Useful if your plugin needs to modify the `app.conf` file. |
| `RUN_SCHD` | (required if you include "schedule" in the above `RUN` function) Cron-like scheduling is used if the `RUN` setting is set to `schedule`. |
| `CMD` | (required) Specifies the command that should be executed. |
| `API_SQL` | (not implemented) Generates a `table_` + `code_name` + `.json` file as per [API docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md). |
| `API_SQL` | (not implemented) Generates a `table_` + `code_name` + `.json` file as per [API docs](./API.md). |
| `RUN_TIMEOUT` | (optional) Specifies the maximum execution time of the script. If not specified, a default value of 10 seconds is used to prevent hanging. |
| `WATCH` | (optional) Specifies which database columns are watched for changes for this particular plugin. If not specified, no notifications are sent. |
| `REPORT_ON` | (optional) Specifies when to send a notification. Supported options are: |

View File

@@ -1,53 +1,32 @@
# Privacy & Random MAC's
<!--- --------------------------------------------------------------------- --->
The latest versions of some operating systems (IOS and Android) incorporate a
new & interesting functionality to improve privacy: **Random MACs**.
Some operating systems incorporate randomize MAC addresses to improve privacy.
This functionality allows you to **hide the real MAC** of the device and
**assign a random MAC** when we connect to WIFI networks.
This functionality allows you to **hide the real MAC** of the device and **assign a random MAC** when we connect to WIFI networks.
This behavior is especially useful when connecting to WIFI's that we do not
know, but it **is totally useless when connecting to our own WIFI's** or known
networks.
This behavior is especially useful when connecting to WIFI's that we do not know, but it **is totally useless when connecting to our own WIFI's** or known networks.
**I recommend disabling this operation when connecting our devices to our own
WIFI's**, in this way, NetAlertX will be able to identify the device, and it
will not identify it as a new device every so often (every time IOS or Android
decides to change the MAC).
**I recommend disabling this on-device functionality when connecting our devices to our own WIFI's**, this way, NetAlertX will be able to identify the device, and it will not identify it as a new device every so often (every time iOS or Android randomizes the MAC).
**Random MACs** are recognized by the characters "2", "6", "A", or "E" as the 2nd character in the Mac address. You can disable specific prefixes to be detected as random MAC addresses by specifying the `UI_NOT_RANDOM_MAC` setting.
## Windows
![windows](./img/RANDOM_MAC/windows_random_mac.png)
- [How to Disable MAC Randomization on Windows](https://www.androidphonesoft.com/blog/how-to-turn-off-random-mac-address-windows-10/)
## IOS
![ios][ios]
![ios](./img/RANDOM_MAC/ios_random_mac.png)
- [Use private Wi-Fi addresses in iOS 14](https://support.apple.com/en-us/HT211227)
## Android
![Android][Android]
![ios](./img/RANDOM_MAC/android_random_mac.jpg)
- [How to Disable MAC Randomization in Android 10](https://support.boingo.com/s/article/How-to-Disable-MAC-Randomization-in-Android-10-Android-Q)
- [How do I disable random Wi-Fi MAC address on Android 10](https://support.plume.com/hc/en-gb/articles/360052070714-How-do-I-disable-random-Wi-Fi-MAC-address-on-Android-10-)
### License
GPL 3.0
[Read more here](../LICENSE.txt)
### Contact
Always use the Issue tracker for the correct fork, for example:
[jokob-sk/NetAlertX](https://github.com/jokob-sk/NetAlertX/issues). Please also follow the guidelines on:
- [Pull Request guidelines](https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs)
- 🙏 [Feature request guidelines](https://github.com/jokob-sk/NetAlertX/tree/main/docs#-feature-requests)
- 🐛 [Issue guidelines](https://github.com/jokob-sk/NetAlertX/tree/main/docs#-submitting-an-issue-or-bug)
***Suggestions and comments are welcome***
<!--- --------------------------------------------------------------------- --->
[ios]: https://9to5mac.com/wp-content/uploads/sites/6/2020/08/how-to-use-private-wifi-mac-address-iphone-ipad.png?resize=2048,1009 "ios"
[Android]: ./img/android_random_mac.jpg "Android"

View File

@@ -3,7 +3,7 @@
<details>
<summary>:information_source: In the app hover over settings or fields/labels or click blue in-app ❔ (question-mark) icons to get to relevant documentation pages.</summary>
![In-app help](/docs/img/GENERAL/in-app-help.png)
![In-app help](./img/GENERAL/in-app-help.png)
</details>
@@ -17,7 +17,7 @@ There is also an in-app Help / FAQ section that should be answering frequently a
#### 💻 Bare-metal / On-server (Experimental/community supported 🧪)
- [(Experimental 🧪) On-hardware instructions](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md)
- [(Experimental 🧪) On-hardware instructions](./HW_INSTALL.md)
- Alternative bare-metal install forks:
- [leiweibau's fork](https://github.com/leiweibau/Pi.Alert/) (maintained)
@@ -27,58 +27,58 @@ There is also an in-app Help / FAQ section that should be answering frequently a
#### 📥 Initial Setup
- [Synology Guide](/docs/SYNOLOGY_GUIDE.md)
- [Subnets and VLANs configuration for arp-scan](/docs/SUBNETS.md)
- [Scanning Remote Networks](/docs/REMOTE_NETWORKS.md)
- [SMTP server config](/docs/SMTP.md)
- [Custom Icon configuration and support](/docs/ICONS.md)
- [Notifications](/docs/NOTIFICATIONS.md)
- [Better name resolution with Reverse DNS](/docs/REVERSE_DNS.md)
- [Network treemap configuration](/docs/NETWORK_TREE.md)
- [Backups](/docs/BACKUPS.md)
- [Plugins overview](/front/plugins/README.md)
- [Synology Guide](./SYNOLOGY_GUIDE.md)
- [Subnets and VLANs configuration for arp-scan](./SUBNETS.md)
- [Scanning Remote Networks](./REMOTE_NETWORKS.md)
- [SMTP server config](./SMTP.md)
- [Custom Icon configuration and support](./ICONS.md)
- [Notifications](./NOTIFICATIONS.md)
- [Better name resolution with Reverse DNS](./REVERSE_DNS.md)
- [Network treemap configuration](./NETWORK_TREE.md)
- [Backups](./BACKUPS.md)
- [Plugins overview](/docs/PLUGINS.md)
#### 🐛 Debugging help & tips
- [Debugging tips](/docs/DEBUG_TIPS.md)
- [Debugging UI not showing](/docs/WEB_UI_PORT_DEBUG.md)
- [Invalid JSON errors debug help](/docs/DEBUG_INVALID_JSON.md)
- [Troubleshooting Plugins](/docs/DEBUG_PLUGINS.md)
- [File Permissions](/docs/FILE_PERMISSIONS.md)
- [Performance tips](/docs/PERFORMANCE.md)
- [Debugging tips](./DEBUG_TIPS.md)
- [Debugging UI not showing](./WEB_UI_PORT_DEBUG.md)
- [Invalid JSON errors debug help](./DEBUG_INVALID_JSON.md)
- [Troubleshooting Plugins](./DEBUG_PLUGINS.md)
- [File Permissions](./FILE_PERMISSIONS.md)
- [Performance tips](./PERFORMANCE.md)
#### 🔝 Popular/Suggested
- [Home Assistant](/docs/HOME_ASSISTANT.md)
- [Bulk edit devices](/docs/DEVICES_BULK_EDITING.md)
- [Home Assistant](./HOME_ASSISTANT.md)
- [Bulk edit devices](./DEVICES_BULK_EDITING.md)
#### ⚙ System Management
- [Manage devices (legacy docs)](/docs/DEVICE_MANAGEMENT.md)
- [Random MAC/MAC icon meaning (legacy docs)](/docs/RANDOM_MAC.md)
- [Manage devices (legacy docs)](./DEVICE_MANAGEMENT.md)
- [Random MAC/MAC icon meaning (legacy docs)](./RANDOM_MAC.md)
#### 🔎 Examples
- [N8N webhook example](/docs/WEBHOOK_N8N.md)
- [N8N webhook example](./WEBHOOK_N8N.md)
#### ♻ Misc
- [Version history (legacy)](/docs/VERSIONS_HISTORY.md)
- [Reverse proxy (Nginx, Apache, SWAG)](/docs/REVERSE_PROXY.md)
- [Installing Updates](/docs/UPDATES.md)
- [Setting up Authelia](/docs/AUTHELIA.md) (DRAFT)
- [Version history (legacy)](./VERSIONS_HISTORY.md)
- [Reverse proxy (Nginx, Apache, SWAG)](./REVERSE_PROXY.md)
- [Installing Updates](./UPDATES.md)
- [Setting up Authelia](./AUTHELIA.md) (DRAFT)
#### 👩💻For Developers👨💻
- [Setting up your DEV environment](/docs/DEV_ENV_SETUP.md)
- [Setting up your DEV environment](./DEV_ENV_SETUP.md)
- [Server APP code structure](/server/README.md)
- [Database structure](/docs/DATABASE.md)
- [API endpoints details](/docs/API.md)
- [Plugin development guide](/docs/PLUGINS_DEV.md)
- [Settings system](/docs/SETTINGS_SYSTEM.md)
- [New Version notifications](/docs/VERSIONS.md)
- [Frontend development tips](/docs/FRONTEND_DEVELOPMENT.md)
- [Webhook secrets](/docs/WEBHOOK_SECRET.md)
- [Database structure](./DATABASE.md)
- [API endpoints details](./API.md)
- [Plugin development guide](./PLUGINS_DEV.md)
- [Settings system](./SETTINGS_SYSTEM.md)
- [New Version notifications](./VERSIONS.md)
- [Frontend development tips](./FRONTEND_DEVELOPMENT.md)
- [Webhook secrets](./WEBHOOK_SECRET.md)
Feel free to suggest or submit new docs via a PR.
@@ -137,8 +137,8 @@ Some additional context:
Before submitting a new issue please spend a couple of minutes on research:
* Check [🛑 Common issues](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md#common-issues)
* Check [🛑 Common issues](./DEBUG_TIPS.md#common-issues)
* Check [💡 Closed issues](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed) if a similar issue was solved in the past.
* When submitting an issue ❗[enable debug](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md)❗
* When submitting an issue ❗[enable debug](./DEBUG_TIPS.md)❗
⚠ Please follow the pre-defined issue template to resolve your issue faster.

View File

@@ -2,11 +2,14 @@
By design, local network scanners such as `arp-scan` use ARP (Address Resolution Protocol) to map IP addresses to MAC addresses on the local network. Since ARP operates at Layer 2 (Data Link Layer), it typically works only within a single broadcast domain, usually limited to a single router or network segment.
To scan multiple locally accessible network segments, add them as subnets according to the [subnets](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) documentation.
> [!NOTE]
> Ping and `ARPSCAN` use different protocols so even if you can ping devices it doesn't mean `ARPSCAN` can detect them.
To scan multiple locally accessible network segments, add them as subnets according to the [subnets](./SUBNETS.md) documentation. If `ARPSCAN` is not suitable for your setup, read on.
## Complex Use Cases
The following network setups might make some devices undetectable. Check the specific setup to understand the cause and find potential workarounds to still report on these devices.
The following network setups might make some devices undetectable with `ARPSCAN`. Check the specific setup to understand the cause and find potential workarounds to report on these devices.
### Wi-Fi Extenders
@@ -28,7 +31,7 @@ The following workarounds should work for most complex network setups.
## Supplementing Plugins
You can use supplementary plugins that employ alternate methods. Protocols used by the `SNMPDSC` or `DHCPLSS` plugins are widely supported on different routers and can be effective as workarounds. Check the [plugins list](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) to find a plugin that works with your router and network setup.
You can use supplementary plugins that employ alternate methods. Protocols used by the `SNMPDSC` or `DHCPLSS` plugins are widely supported on different routers and can be effective as workarounds. Check the [plugins list](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) to find a plugin that works with your router and network setup.
## Multiple NetAlertX Instances
@@ -38,7 +41,7 @@ If you have servers in different networks, you can set up separate NetAlertX ins
If you don't need to discover new devices and only need to report on their status (`online`, `offline`, `down`), you can manually enter devices and check their status using the [`ICMP` plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/icmp_scan/), which uses the `ping` command internally.
For more information on how to add devices manually (or dummy devices), refer to the [Device Management](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICE_MANAGEMENT.md) documentation.
For more information on how to add devices manually (or dummy devices), refer to the [Device Management](./DEVICE_MANAGEMENT.md) documentation.
To create truly dummy devices, you can use a loopback IP address (e.g., `0.0.0.0` or `127.0.0.1`) so they appear online.

View File

@@ -8,7 +8,6 @@ If you are running a DNS server, such as **AdGuard**, set up **Private reverse D
> ```
> jokob@Synology-NAS:/$ nslookup 192.168.1.58
> ** server can't find 58.1.168.192.in-addr.arpa: NXDOMAIN
>
> ```
> Example 2: Reverse DNS `enabled`
@@ -35,7 +34,7 @@ You can specify the DNS server in the docker-compose to improve name resolution
services:
netalertx:
container_name: netalertx
image: "jokobsk/netalertx:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
restart: unless-stopped
volumes:
- /home/netalertx/config:/app/config
@@ -61,7 +60,7 @@ version: "3"
services:
netalertx:
container_name: netalertx
image: "jokobsk/netalertx:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
restart: unless-stopped
volumes:
- ./config/app.conf:/app/config/app.conf

View File

@@ -477,7 +477,7 @@ docker run -d --rm --network=host \
-v /appl/docker/netalertx/default:/etc/nginx/sites-available/default \
-e TZ=Europe/Amsterdam \
-e PORT=20211 \
jokobsk/netalertx:latest
ghcr.io/jokob-sk/netalertx:latest
```

29
docs/SECURITY.md Executable file
View File

@@ -0,0 +1,29 @@
# Securing your NetAlertX instance
NetAlertX is an execution framework. In order to run scanners and plugins, the application has to have access to privileged system resources. It is not recommended to expose NetAlertX to the internet without taking basic security precautions. It is highly recommended to use a VPN to access the application and to set up a password for the web interface before exposing the UI online.
## VPN
VPNs allow you to securely access your NetAlertX instance from remote locations without exposing it to the internet. A VPN encrypts your connection and prevents unauthorized access.
### Tailscale as an Alternative
If setting up a traditional VPN is not ideal, you can use [Tailscale](https://tailscale.com/) as an easy alternative. Tailscale creates a secure, encrypted connection between your devices without complex configuration. Since NetAlertX is designed to be run on private networks, Tailscale can provide a simple way to securely connect to your instance from anywhere.
## Setting a Password
By default, NetAlertX does not enforce authentication, but it is highly recommended to set a password before exposing the web interface.
Configure `SETPWD_enable_password` to `true` and enter your password in `SETPWD_password`. When enabled, a login dialog is displayed. If facing issues, you can always disable the login by setting `SETPWD_enable_password=false` in your `app.conf` file.
- The default password is `123456`.
- Passwords are stored as SHA256 hashes for security.
## Additional Security Measures
- **Firewall Rules**: Ensure that only trusted IPs can access the NetAlertX instance.
- **Limit Plugin Permissions**: Only enable the plugins necessary for your setup.
- **Keep Software Updated**: Regularly update NetAlertX to receive the latest security patches.
- **Use Read-Only API Keys**: If exposing APIs, limit privileges with read-only keys where applicable.
By following these security recommendations, you can help protect your NetAlertX instance from unauthorized access and potential misuse.

View File

@@ -2,7 +2,7 @@
The **Sessions Section** provides details about a device's connection history. This data is automatically detected and cannot be edited by the user.
![Session info](/docs/img/SESSION_INFO/DeviceDetails_SessionInfo.png)
![Session info](./img/SESSION_INFO/DeviceDetails_SessionInfo.png)
---
@@ -57,6 +57,6 @@ When a new connection is detected, the system creates a session record:
The session information is then used to display the device presence under **Monitoring** -> **Presence**.
![Monitoring Device Presence](/docs/img/SESSION_INFO/Monitoring_Presence.png)
![Monitoring Device Presence](./img/SESSION_INFO/Monitoring_Presence.png)

View File

@@ -10,11 +10,11 @@ The source of truth for user-defined values is the `app.conf` file. Editing the
#### Settings database table
The `Settings` database table contains settings for App run purposes. The table is recreated every time the App restarts. The settings are loaded from the source-of-truth, that is the `app.conf` file. A high-level overview on the database structure can be found in the [database documentation](/docs/DATABASE.md).
The `Settings` database table contains settings for App run purposes. The table is recreated every time the App restarts. The settings are loaded from the source-of-truth, that is the `app.conf` file. A high-level overview on the database structure can be found in the [database documentation](./DATABASE.md).
#### table_settings.json
This is the [API endpoint](/docs/API.md) that reflects the state of the `Settings` database table. Settings can be accessed with the:
This is the [API endpoint](./API.md) that reflects the state of the `Settings` database table. Settings can be accessed with the:
* `getSetting(key)` JavaScript method
@@ -32,7 +32,7 @@ The App generates two `app.conf` entries for every setting (Since version 23.8+)
> [!NOTE]
> This is the preferred way adding settings going forward. I'll be likely migrating all app settings into plugin-based settings.
Plugin settings are loaded dynamically from the `config.json` of individual plugins. If a setting isn't defined in the `app.conf` file, it is initialized via the `default_value` property of a setting from the `config.json` file. Check the [Plugins documentation](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md#-setting-object-structure), section `⚙ Setting object structure` for details on the structure of the setting.
Plugin settings are loaded dynamically from the `config.json` of individual plugins. If a setting isn't defined in the `app.conf` file, it is initialized via the `default_value` property of a setting from the `config.json` file. Check the [Plugins documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md#-setting-object-structure), section `⚙ Setting object structure` for details on the structure of the setting.
![Screen 1][screen1]

View File

@@ -2,29 +2,36 @@
You need to specify the network interface and the network mask. You can also configure multiple subnets and specify VLANs (see VLAN exceptions below).
`ARPSCAN` can scan multiple networks if the network allows it. To scan networks directly, the subnets must be accessible from the network where NetAlertX is running. This means NetAlertX needs to have access to the interface attached to that subnet. You can verify this by running the following command in the container (replace the interface and ip mask):
`ARPSCAN` can scan multiple networks if the network allows it. To scan networks directly, the subnets must be accessible from the network where NetAlertX is running. This means NetAlertX needs to have access to the interface attached to that subnet.
`sudo arp-scan --interface=eth0 192.168.1.0/24`
> [!WARNING]
> If you don't see all expected devices run the following command in the NetAlertX container (replace the interface and ip mask):
> `sudo arp-scan --interface=eth0 192.168.1.0/24`
>
> If this command returns no results, the network is not accessible due to your network or firewall restrictions (Wi-Fi Extenders, VPNs and inaccessible networks). If direct scans are not possible, check the [remote networks documentation](./REMOTE_NETWORKS.md) for workarounds.
In this example, `--interface=eth0 192.168.1.0/24` represents a neighboring subnet. If this command returns no results, the network is not accessible due to your network or firewall restrictions.
If direct scans are not possible (Wi-Fi Extenders, VPNs and inaccessible networks), check the [remote networks documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md).
> [!TIP]
> You may need to increase the time between scans `ARPSCAN_RUN_SCHD` and the timeout `ARPSCAN_RUN_TIMEOUT` (and similar settings for related plugins) when adding more subnets. If the timeout setting is exceeded, the scan is canceled to prevent the application from hanging due to rogue plugins.
> Check [debugging plugins](/docs/DEBUG_PLUGINS.md) for more tips.
## Example Values
> [!NOTE]
> Please use the UI to configure settings as it ensures the config file is in the correct format. Edit `app.conf` directly only when really necessary.
> ![Settings location](/docs/img/SUBNETS/subnets-setting-location.png)
> ![Settings location](./img/SUBNETS/subnets-setting-location.png)
* **Examples for one and two subnets:**
* One subnet: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0']`
* Two subnets: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0','192.168.1.0/24 --interface=eth1 --vlan=107']`
If you get timeout messages, decrease the network mask (e.g.: from `/16` to `/24`) or increase the `TIMEOUT` setting (e.g.: `ARPSCAN_RUN_TIMEOUT` to `300` (5-minute timeout)) for the plugin and the interval between scans (e.g.: `ARPSCAN_RUN_SCHD` to `*/10 * * * *` (scans every 10 minutes)).
> [!TIP]
> When adding more subnets, you may need to increase both the scan interval (`ARPSCAN_RUN_SCHD`) and the timeout (`ARPSCAN_RUN_TIMEOUT`)—as well as similar settings for related plugins.
>
> If the timeout is too short, you may see timeout errors in the log. To prevent the application from hanging due to unresponsive plugins, scans are canceled when they exceed the timeout limit.
>
> To fix this:
> - Reduce the subnet size (e.g., change `/16` to `/24`).
> - Increase the timeout (e.g., set `ARPSCAN_RUN_TIMEOUT` to `300` for a 5-minute timeout).
> - Extend the scan interval (e.g., set `ARPSCAN_RUN_SCHD` to `*/10 * * * *` to scan every 10 minutes).
>
> For more troubleshooting tips, see [Debugging Plugins](./DEBUG_PLUGINS.md).
---
@@ -47,7 +54,7 @@ Specify the network filter, which **significantly** speeds up the scan process.
The adapter will probably be `eth0` or `eth1`. (Check `System Info` > `Network Hardware`, or run `iwconfig` in the container to find your interface name(s)).
![Network hardware](/docs/img/SUBNETS/system_info-network_hardware.png)
![Network hardware](./img/SUBNETS/system_info-network_hardware.png)
> [!TIP]
> As an alternative to `iwconfig`, run `ip -o link show | awk -F': ' '!/lo|vir|docker/ {print $2}'` in your container to find your interface name(s) (e.g.: `eth0`, `eth1`):

View File

@@ -9,18 +9,18 @@ The folders you are creating below will contain the configuration and the databa
1. Create a parent folder named `netalertx`
2. Create a `db` sub-folder
![Folder structure](/docs/img/SYNOLOGY/01_Create_folder_structure.png)
![Folder structure](/docs/img/SYNOLOGY/02_Create_folder_structure_db.png)
![Folder structure](/docs/img/SYNOLOGY/03_Create_folder_structure_db.png)
![Folder structure](./img/SYNOLOGY/01_Create_folder_structure.png)
![Folder structure](./img/SYNOLOGY/02_Create_folder_structure_db.png)
![Folder structure](./img/SYNOLOGY/03_Create_folder_structure_db.png)
3. Create a `config` sub-folder
![Folder structure](/docs/img/SYNOLOGY/04_Create_folder_structure_config.png)
![Folder structure](./img/SYNOLOGY/04_Create_folder_structure_config.png)
4. Note down the folders Locations:
![Getting the location](/docs/img/SYNOLOGY/05_Access_folder_properties.png)
![Getting the location](/docs/img/SYNOLOGY/06_Note_location.png)
![Getting the location](./img/SYNOLOGY/05_Access_folder_properties.png)
![Getting the location](./img/SYNOLOGY/06_Note_location.png)
5. Open **Container manager** -> **Project** and click **Create**.
6. Fill in the details:
@@ -35,8 +35,8 @@ services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
@@ -49,7 +49,7 @@ services:
- PORT=20211
```
![Project settings](/docs/img/SYNOLOGY/07_Create_project.png)
![Project settings](./img/SYNOLOGY/07_Create_project.png)
7. Replace the paths to your volume and/or comment out unnecessary line(s):
@@ -63,12 +63,12 @@ services:
# - local/path/logs:/app/log <- commented out with # ⚠
```
![Adjusting docker-compose](/docs/img/SYNOLOGY/08_Adjust_docker_compose_volumes.png)
![Adjusting docker-compose](./img/SYNOLOGY/08_Adjust_docker_compose_volumes.png)
8. (optional) Change the port number from `20211` to an unused port if this port is already used.
9. Build the project:
![Build](/docs/img/SYNOLOGY/09_Run_and_build.png)
![Build](./img/SYNOLOGY/09_Run_and_build.png)
10. Navigate to `<Synology URL>:20211` (or your custom port).
11. Read the [Subnets](/docs/SUBNETS.md) and [Plugins](/front/plugins/README.md) docs to complete your setup.
11. Read the [Subnets](./SUBNETS.md) and [Plugins](/docs/PLUGINS.md) docs to complete your setup.

View File

@@ -1,6 +1,6 @@
# Docker Update Strategies for NetAlertX
# Docker Update Strategies to upgrade NetAlertX
This guide outlines several approaches for updating Docker containers, specifically using NetAlertX. Each method offers different benefits depending on the situation. Here are the methods:
This guide outlines approaches for updating Docker containers, usually when upgrading to a newer version of NetAlertX. Each method offers different benefits depending on the situation. Here are the methods:
- Manual: Direct commands to stop, remove, and rebuild containers.
- Dockcheck: Semi-automated with more control, suited for bulk updates.
@@ -10,6 +10,9 @@ You can choose any approach that fits your workflow.
> In the examples I assume that the container name is `netalertx` and the image name is `netalertx` as well.
> [!NOTE]
> See also [Backup strategies](./BACKUPS.md) to be on the safe side.
## 1. Manual Updates
Use this method when you need precise control over a single container or when dealing with a broken container that needs immediate attention.

View File

@@ -8,17 +8,17 @@ If you are not on the latest version, the app will notify you, that a new releas
If any notification occurs and an email is sent, the email will contain a note that a new version is available. See the sample email below:
![Sample email if a new version is available](/docs/img/VERSIONS/new-version-available-email.png)
![Sample email if a new version is available](./img/VERSIONS/new-version-available-email.png)
### 🆕 In the UI
In the UI via a notification Icon and via a custom message in the Maintenance section.
![UI screenshot if a new version is available](/docs/img/VERSIONS/new-version-available-maintenance.png)
![UI screenshot if a new version is available](./img/VERSIONS/new-version-available-maintenance.png)
For a comparison, this is how the UI looks like if you are on the latest stable image:
![UI screenshot if on latest version](/docs/img/VERSIONS/latest-version-maintenance.png)
![UI screenshot if on latest version](./img/VERSIONS/latest-version-maintenance.png)
## Implementation details

View File

@@ -2,11 +2,11 @@
N8N can be used for more advanced conditional notification use cases. For example, you want only to get notified if two out of a specified list of devices is down. Or you can use other plugins to process the notifiations further. The below is a simple example of sending an email on a webhook.
![n8n workflow](/docs/img/WEBHOOK_N8N/n8n_workflow.png)
![n8n workflow](./img/WEBHOOK_N8N/n8n_workflow.png)
### Specify your email template
See [sample JSON](https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json) if you want to see the JSON paths used in the email template below
![Email template](/docs/img/WEBHOOK_N8N/n8n_send_email_settings.png)
![Email template](./img/WEBHOOK_N8N/n8n_send_email_settings.png)
```
Events count: {{ $json["body"]["attachments"][0]["text"]["events"].length }}
@@ -14,7 +14,7 @@ New devices count: {{ $json["body"]["attachments"][0]["text"]["new_devices"].len
```
### Get your webhook in n8n
![n8n webhook URL](/docs/img/WEBHOOK_N8N/n8n_webhook_settings.png)
![n8n webhook URL](./img/WEBHOOK_N8N/n8n_webhook_settings.png)
### Configure NetAlertX to point to the above URL
![NetAlertX config](/docs/img/WEBHOOK_N8N/Webhook_settings.png)
![NetAlertX config](./img/WEBHOOK_N8N/Webhook_settings.png)

View File

@@ -5,7 +5,7 @@
When opening an issue please:
1. Include a screenshot of what you see when accessing `HTTP://<your rpi IP>/20211` (or your custom port)
1. [Follow steps 1, 2, 3, 4 on this page](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md)
1. [Follow steps 1, 2, 3, 4 on this page](./DEBUG_TIPS.md)
1. Execute the following in the container to see the processes and their ports and submit a screenshot of the result:
1. `sudo apk add lsof`
1. `sudo lsof -i`
@@ -13,7 +13,7 @@ When opening an issue please:
1. if you get `nginx: [emerg] bind() to 0.0.0.0:20211 failed (98: Address in use)` try using a different port number
![lsof ports](/docs/img/WEB_UI_PORT_DEBUG/container_port.png)
![lsof ports](./img/WEB_UI_PORT_DEBUG/container_port.png)
## 2. JavaScript issues
@@ -48,4 +48,4 @@ In the container execute:
> [!TIP]
> You can try to start the container without mapping the `/app/config` and `/app/db` dirs and if the UI shows up then the issue is most likely related to your file system permissions or file ownership.
Please read the [Permissions troubleshooting guide](/docs/FILE_PERMISSIONS.md) and provide a screesnhot of the permissions and ownership in the `/app/db` and `app/config` directories.
Please read the [Permissions troubleshooting guide](./FILE_PERMISSIONS.md) and provide a screesnhot of the permissions and ownership in the `/app/db` and `app/config` directories.

125
docs/WORKFLOWS.md Executable file
View File

@@ -0,0 +1,125 @@
# Workflows Overview
The workflows module in NetAlertX allows to automate repetitive tasks, making network management more efficient. Whether you need to assign newly discovered devices to a specific Network Node, auto-group devices from a given vendor, unarchive a device if detected online, or automatically delete devices, this module provides the flexibility to tailor the automations to your needs.
![Workflows diagram](./img/WORKFLOWS/workflows_diagram.png)
Below are a few examples that demonstrate how this module can be used to simplify network management tasks.
## Updating Workflows
> [!NOTE]
> In order to apply a workflow change, you must first **Save** the changes and then reload the application by clicking **Restart server**.
## Workflow components
### Triggers
Triggers define the event that activates a workflow. They monitor changes to objects within the system, such as updates to devices or the insertion of new entries. When the specified event occurs, the workflow is executed.
#### Example Trigger:
- **Object Type**: `Devices`
- **Event Type**: `update`
This trigger will activate when a `Device` object is updated.
### Conditions
![Conditions example](./img/WORKFLOWS/conditions.png)
Conditions determine whether a workflow should proceed based on certain criteria. These criteria can be set for specific fields, such as whether a device is from a certain vendor, or whether it is new or archived. You can combine conditions using logical operators (`AND`, `OR`).
> [!TIP]
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
### Example Condition:
- **Logic**: `AND`
- **Field**: `devVendor`
- **Operator**: `contains` (case in-sensitive)
- **Value**: `Google`
This condition checks if the device's vendor is `Google`. The workflow will only proceed if the condition is true.
### Actions
![Actions example](./img/WORKFLOWS/actions.jpg)
Actions define the tasks that the workflow will perform once the conditions are met. Actions can include updating fields or deleting devices.
You can include multiple actions that should execute once the conditions are met.
### Example Action:
- **Action Type**: `update_field`
- **Field**: `devIsNew`
- **Value**: `0`
This action updates the `devIsNew` field to `0`, marking the device as no longer new.
# Examples
Below you can find a couple of configuration examples.
![Workflow example](./img/WORKFLOWS/workflows.png)
---
## Example 1: Assign Device to Network Node Based on IP
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to the device with the MAC address `6c:6d:6d:6c:6c:6c`.
### Trigger:
- **Object Type**: `Devices`
- **Event Type**: `insert`
### Conditions:
- **Logic**: `AND`
- `Field`: `devLastIP`
- `Operator`: `contains`
- `Value`: `192.168.1.`
This condition ensures that the workflow only applies to devices with an IP address in the `192.168.1.*` range.
### Actions:
- **Action Type**: `update_field`
- **Field**: `devNetworkNode`
- **Value**: `6c:6d:6d:6c:6c:6c`
---
## Example 2: Mark Device as Not New and Delete If from Google Vendor
This workflow automates the process of marking Google devices as not new and deleting them if they meet the criteria.
### Trigger:
- **Object Type**: `Devices`
- **Event Type**: `update`
### Conditions:
- **Logic**: `AND`
- `Field`: `devVendor`
- `Operator`: `contains`
- `Value`: `Google`
This condition checks if the device's vendor is `Google`.
- **Logic**: `AND`
- `Field`: `devIsNew`
- `Operator`: `equals`
- `Value`: `1`
This ensures the workflow applies only to new devices.
### Actions:
1. **Action Type**: `update_field`
- **Field**: `devIsNew`
- **Value**: `0`
This action marks the device as no longer new.
2. **Action Type**: `delete_device`
This action deletes the device after it is marked as not new.
> [!TIP]
> Share your workflows in [Discord](https://discord.com/invite/NczTUTWyRr) or [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions).

BIN
docs/img/NetAlertX_logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 551 KiB

After

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/img/WORKFLOWS/actions.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/img/WORKFLOWS/conditions.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/img/WORKFLOWS/workflows.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
docs/img/netalertx_docs.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

79
docs/index.md Executable file
View File

@@ -0,0 +1,79 @@
# NetAlertX Documentation
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
NetAlertX provides contextual help within the application:
- **Hover over settings, fields, or labels** to see additional tooltips and guidance.
- **Click ❔ (question-mark) icons** next to various elements to view detailed information.
---
## Installation Guides
### Docker (Fully Supported)
NetAlertX is fully supported in Docker environments, allowing for easy setup and configuration. Follow the official guide to get started:
- [Docker Installation Guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
This guide will take you through the process of setting up NetAlertX using Docker Compose or standalone Docker commands.
### 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.
- [Bare-Metal Installation Guide](./HW_INSTALL.md)
---
## Help and Support
If you need help or run into issues, here are some resources to guide you:
**Before opening an issue, please:**
- [Check common issues](./DEBUG_TIPS.md#common-issues) to see if your problem has already been reported.
- [Look at closed issues](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed) for possible solutions to past problems.
- **Enable debugging** to gather more information: [Debug Guide](./DEBUG_TIPS.md).
**Need more help?** Join the community discussions or submit a support request:
- Visit the [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions) for community support.
- If you are experiencing issues that require immediate attention, consider opening an issue on our [GitHub Issues page](https://github.com/jokob-sk/NetAlertX/issues).
---
## Contributing
NetAlertX is open-source and welcomes contributions from the community! If you'd like to help improve the software, please follow the guidelines below:
- **Fork the repository** and make your changes.
- **Submit a pull request** with a detailed description of what youve changed and why.
For more information on contributing, check out our [Dev Guide](./DEV_ENV_SETUP.md).
---
## Stay Updated
To keep up with the latest changes and updates to NetAlertX, please refer to the following resources:
- [Releases](https://github.com/jokob-sk/NetAlertX/releases)
Make sure to follow the project on GitHub to get notifications for new releases and important updates.
---
## 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.
We hope you find this documentation helpful. If you have any suggestions or improvements, please dont 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).

28
docs/overrides/main.html Executable file
View File

@@ -0,0 +1,28 @@
{% extends "base.html" %}
{% block analytics %}
<!-- Google Tag Manager -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-KCRSGLP8J2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-KCRSGLP8J2');
</script>
<!-- End Google Tag Manager -->
{{ super() }}
{% endblock %}
{% block header %}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KCRSGLP8J2"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{{ super() }}
{% endblock %}

21
front/appEvents.php Executable file
View File

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

View File

@@ -1,9 +1,9 @@
<section class="content">
<div class="nav-tabs-custom app-event-content" style="margin-bottom: 0px;">
<ul id="tabs-location" class="nav nav-tabs col-sm-2">
<ul id="tabs-location" class="nav nav-tabs col-sm-2 hidden">
<li class="left-nav"><a class="col-sm-12" href="#" id="" data-toggle="tab">Events</a></li>
</ul>
<div id="tabs-content-location" class="tab-content col-sm-10">
<div id="tabs-content-location" class="tab-content col-sm-12">
<table class="table table-striped" id="appevents-table" data-my-dbtable="AppEvents"></table>
</div>
</div>
@@ -43,6 +43,9 @@ function processData(data) {
});
console.log(allData);
// Initialize DataTable for all app events
$('#appevents-table').DataTable({
@@ -57,22 +60,24 @@ function processData(data) {
pageLength: 25, // Set the default paging to 25
columns: [
{ data: 'DateTimeCreated', title: getString('AppEvents_DateTimeCreated') },
{ data: 'AppEventProcessed', title: getString('AppEvents_AppEventProcessed') },
{ data: 'AppEventType', title: getString('AppEvents_Type') },
{ data: 'ObjectType', title: getString('AppEvents_ObjectType') },
{ data: 'ObjectPrimaryID', title: getString('AppEvents_ObjectPrimaryID') },
{ data: 'ObjectSecondaryID', title: getString('AppEvents_ObjectSecondaryID') },
{ data: 'ObjectStatus', title: getString('AppEvents_ObjectStatus') },
{ data: 'Extra', title: getString('AppEvents_Extra') },
{ data: 'ObjectPlugin', title: getString('AppEvents_Plugin') },
{ data: 'ObjectGUID', title: "Object GUID" },
{ data: 'GUID', title: "Event GUID" },
// Add other columns as needed
],
// Add column-specific configurations if needed
columnDefs: [
{ className: 'text-center', targets: [3] },
{ width: '80px', targets: [6] },
{ className: 'text-center', targets: [4] },
{ width: '80px', targets: [7] },
// ... Add other columnDefs as needed
// Full MAC
{targets: [3, 4],
{targets: [4, 5],
'createdCell': function (td, cellData, rowData, row, col) {
if (!emptyArr.includes(cellData)){
$(td).html (createDeviceLink(cellData));
@@ -80,6 +85,37 @@ function processData(data) {
$(td).html ('');
}
} },
// Processed
{targets: [1],
'createdCell': function (td, cellData, rowData, row, col) {
// console.log(cellData);
$(td).html (cellData);
}
},
// Datetime
{targets: [0],
'createdCell': function (td, cellData, rowData, row, col) {
let timezone = $("#NAX_TZ").html(); // e.g., 'Europe/Berlin'
let utcDate = new Date(cellData + ' UTC'); // Adding ' UTC' makes it interpreted as UTC time
// Format the date in the desired timezone
let options = {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // Use 24-hour format
timeZone: timezone // Use the specified timezone
};
let localDate = new Intl.DateTimeFormat('en-GB', options).format(utcDate);
// Update the table cell
$(td).html(localDate);
}
},
]
});

View File

@@ -1141,14 +1141,14 @@ input[readonly] {
.settings-sticky-bottom-section {
position: fixed;
z-index: 999;
background-color: #5B5B66;
/* background-color: #5B5B66; */
/* opacity: 0.8; */
bottom: 30px;
border-radius: 5px;
/* margin:1px; */
border-width: 1px;
/* border-width: 1px;
border-style: solid;
border-color: inherit;
border-color: inherit; */
/* width: 87%; */
padding: 10px;
}
@@ -1245,6 +1245,24 @@ input[readonly] {
/* Devices page */
/* ----------------------------------------------------------------- */
#columnFilters {
display: flex;
flex-wrap: wrap;
gap: 10px; /* Add spacing between items */
}
.filter-group {
box-sizing: border-box; /* Ensure padding and borders are included in the width */
padding: 1em;
padding-top: 0;
}
.filter-dropdown
{
width:7em
}
.modal-header .close
{
display: flex;
@@ -1331,8 +1349,8 @@ input[readonly] {
top: -6px;
position: absolute;
z-index: 1;
left: 0px;
font-size: large;
left: 4px;
font-size: smaller;
}
.drag
@@ -1397,6 +1415,7 @@ input[readonly] {
{
display: none;
padding-top: 2em;
cursor: default;
}
/* ----------------------------------------------------------------- */
@@ -1498,17 +1517,25 @@ input[readonly] {
/* AdminLTE overrides */
#networkTree .box
{
border-top:1px;
/* border-top:1px; */
border-top-color:grey;
padding:0px;
padding-top:6px;
margin:0px;
align-items:center;
border-radius:20px;
width:180px;
display:flex;
/* width:190px; Don't change, smaller causes line break in network view */
/* display:flex; */
flex-direction:column;
justify-content:center;
/* display: inline-grid; */
}
.helpIcon
{
padding: 5px;
margin-left: 0px;
top: 47px;
position: absolute;
z-index: 5;
}
#networkTree .netNodeText
{
@@ -1549,17 +1576,16 @@ input[readonly] {
width: auto;
}
#networkTree .netCollapse
{
display: block;
position: absolute;
margin-left: 170px;
font-size: large;
left: -15px;
right: 0;
margin-right: -3px;
}
#networkTree .highlightedNode
{
border: solid;
/* border: solid; */
border-color:cyan;
}
#networkTree .netStatus-Off-line i,
@@ -1570,7 +1596,6 @@ input[readonly] {
.spanNetworkTree {
display: inline-block;
width: 120px;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;
@@ -1586,6 +1611,11 @@ input[readonly] {
/* margin-left: 0.2em; */
}
.networkTable .networkNodeTabHeaders a {
display: block;
height: 3em;
}
.networkTable .icon {
/* padding-left:2em; */
width:2em;
@@ -1604,7 +1634,6 @@ input[readonly] {
.networkNodeTabHeaders
{
max-width: 200px;
text-overflow: ellipsis;
overflow: hidden;
text-wrap: nowrap;
@@ -1616,6 +1645,24 @@ input[readonly] {
{
display: none;
}
.dev-detail-tab-name
{
display: none;
}
}
/* ----------------------------------------------------------------- */
/* EVENTS page */
/* ----------------------------------------------------------------- */
.eventsPeriodSelectWrap{
display: inline;
float: right;
}
.eventsPage #tableEventsTitle
{
float: left ;
}
/* ----------------------------------------------------------------- */
@@ -1664,13 +1711,6 @@ input[readonly] {
padding-top: 20px;
}
.login-page .login-custom
{
width:480px;
}
/*Hidden special button*/
@media (max-width: 365px) {
@@ -1795,15 +1835,180 @@ input[readonly] {
height:50px;
}
/* -----------------------------------------------------------------------------
Workflows
----------------------------------------------------------------------------- */
#wf-content-wrapper
{
display: grid;
}
#workflowContainer
{
display: grid;
}
#workflowContainerWrap {
display: grid;
}
#workflowContainerWrap .panel-collapse
{
padding: 5px;
}
.workflows .col-sm-12, .workflows .col-sx-12
{
padding-right: 5px;
padding-left: 5px;
}
.workflows .add-button-wrap .button-container
{
padding-bottom: 5px;
text-align: center;
}
.workflows .actions-list {
display: block;
}
.workflows .form-group {
margin-bottom: 7px;
z-index: 1;
display: flex;
opacity: 0.7;
}
.workflows .section-title
{
padding: 10px;
font-weight: bolder;
font-size: large;
}
.workflows .panel, .workflows .box {
padding-top: 5px;
padding-bottom: 5px;
}
.workflows .btn-secondary{
color: #000;
}
.workflows .button-container
{
/* display: contents; */
text-align: center;
/* width: 100%; */
}
/* .workflows .panel:hover{
opacity: 1;
}
.workflows .panel{
opacity: 0.8;
} */
.workflows .bottom-buttons button
{
margin: 5px;
}
.workflows .button-container
{
padding-right: 0px !important;
padding-left: 0px !important;
}
/* .workflows .condition-list button
{
margin: 2px;
} */
/* .button-container button
{
width:100%;
} */
.red-hover-text:hover
{
color: var(--color-red) !important;
}
.green-hover-text:hover
{
color: var(--color-green) !important;
}
.workflows .bckg-icon-1-line
{
font-size: 3em;
display: block;
position: absolute;
opacity: 0.1;
right: 0.1em;
}
.workflows .bckg-icon-2-line
{
font-size: 6em;
display: block;
position: absolute;
opacity: 0.1;
right: 0.1em;
}
.workflows .bckg-icon-3-line
{
font-size: 9em;
display: block;
position: absolute;
opacity: 0.1;
right: 0.1em;
}
.workflows .remove-condition
{
z-index: 1;
}
.workflows .workflow-card
{
display: block;
}
.workflow-card .panel-title
{
padding: 10px;
}
.workflow-card, .actions-list
{
display: contents;
padding: 5px;
padding-left: 10px;
}
.condition-list
{
z-index:1;
}
.condition
{
padding: 5px;
padding-left: 10px;
}
/* -----------------------------------------------------------------------------
Floating edit button
----------------------------------------------------------------------------- */
#multiEditPlc
{
position: fixed;
bottom: 50px;
right: 0px;
z-index: 10;
padding-right: 10px;
}

View File

@@ -745,3 +745,4 @@
{
color:#000;
}

View File

@@ -61,12 +61,54 @@
<!-- <div class="box-transparent"> -->
<div id="navDevice" class="nav-tabs-custom">
<ul class="nav nav-tabs" style="font-size:16px;">
<li> <a id="tabDetails" href="#panDetails" data-toggle="tab"> <?= lang('DevDetail_Tab_Details');?> </a></li>
<li> <a id="tabTools" href="#panTools" data-toggle="tab"> <?= lang('DevDetail_Tab_Tools');?> </a></li>
<li> <a id="tabSessions" href="#panSessions" data-toggle="tab"> <?= lang('DevDetail_Tab_Sessions');?> </a></li>
<li> <a id="tabPresence" href="#panPresence" data-toggle="tab"> <?= lang('DevDetail_Tab_Presence');?> </a></li>
<li> <a id="tabEvents" href="#panEvents" data-toggle="tab"> <?= lang('DevDetail_Tab_Events');?> </a></li>
<li> <a id="tabPlugins" href="#panPlugins" data-toggle="tab"> <?= lang('DevDetail_Tab_Plugins');?> </a></li>
<li>
<a id="tabDetails" href="#panDetails" data-toggle="tab">
<i class="fa fa-info-circle"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Details');?>
</span>
</a>
</li>
<li>
<a id="tabTools" href="#panTools" data-toggle="tab">
<i class="fa fa-screwdriver-wrench"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Tools');?>
</span>
</a>
</li>
<li>
<a id="tabSessions" href="#panSessions" data-toggle="tab">
<i class="fa fa-list-ol"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Sessions');?>
</span>
</a>
</li>
<li>
<a id="tabPresence" href="#panPresence" data-toggle="tab">
<i class="fa fa-calendar"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Presence');?>
</span>
</a>
</li>
<li>
<a id="tabEvents" href="#panEvents" data-toggle="tab">
<i class="fa fa-bolt"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Events');?>
</span>
</a>
</li>
<li>
<a id="tabPlugins" href="#panPlugins" data-toggle="tab">
<i class="fa fa-plug"></i>
<span class="dev-detail-tab-name">
<?= lang('DevDetail_Tab_Plugins');?>
</span>
</a>
</li>
<div class="btn-group pull-right">
<button type="button" class="btn btn-default" style="padding: 10px; min-width: 30px;"

View File

@@ -348,9 +348,10 @@
const createNew = mac === 'new' ? 1 : 0;
const devLastIP = $('#NEWDEV_devLastIP').val();
const newMac = $('#NEWDEV_devMac').val()
// Validate MAC and Last IP
if (mac === '' || !(isValidIPv4(devLastIP) || isValidIPv6(devLastIP))) {
if (mac === '' || !isValidMac(newMac) || !( isValidIPv4(devLastIP) || isValidIPv6(devLastIP) )) {
showMessage(getString("DeviceEdit_ValidMacIp"), 5000, "modal_red");
return;
}
@@ -360,14 +361,14 @@
// Update data to server using POST
$.post('php/server/devices.php?action=setDeviceData', {
mac: $('#NEWDEV_devMac').val(),
name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")),
owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "")),
name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")),
owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "")),
type: $('#NEWDEV_devType').val().replace(/'/g, ""),
vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")),
vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")),
icon: encodeURIComponent($('#NEWDEV_devIcon').val()),
favorite: ($('#NEWDEV_devFavorite')[0].checked * 1),
group: encodeURIComponent($('#NEWDEV_devGroup').val().replace(/'/g, "")),
location: encodeURIComponent($('#NEWDEV_devLocation').val().replace(/'/g, "")),
group: encodeURIComponent($('#NEWDEV_devGroup').val().replace(/'/g, "")),
location: encodeURIComponent($('#NEWDEV_devLocation').val().replace(/'/g, "")),
comments: encodeURIComponent(encodeSpecialChars($('#NEWDEV_devComments').val())),
networknode: $('#NEWDEV_devParentMAC').val(),
networknodeport: $('#NEWDEV_devParentPort').val(),
@@ -403,7 +404,6 @@
// Everything loaded
hideSpinner();
});
}
//-----------------------------------------------------------------------------------

View File

@@ -28,21 +28,12 @@
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
<!-- Content header--------------------------------------------------------- -->
<section class="content-header">
<h1 id="pageTitle">
<i class="fa fa-laptop"></i>
<?= lang('Device_Title');?>
</h1>
</section>
<!-- Main content ---------------------------------------------------------- -->
<section class="content">
<!-- Tile toggle cards ------------------------------------------------------- -->
<div class="row " id="TileCards">
<!-- Placeholder ------------------------------------------------------- -->
</div>
<!-- Device presence / Activity Chart ------------------------------------------------------- -->
@@ -50,8 +41,8 @@
<div class="row" id="DevicePresence">
<div class="col-md-12">
<div class="box" id="clients">
<div class="box-header with-border">
<h3 class="box-title"><?= lang('Device_Shortcut_OnlineChart');?> </h3>
<div class="box-header ">
<h3 class="box-title col-md-12"><?= lang('Device_Shortcut_OnlineChart');?> </h3>
</div>
<div class="box-body">
<div class="chart">
@@ -67,6 +58,15 @@
</div>
</div>
<!-- Device Filters ------------------------------------------------------- -->
<div class="box box-aqua hidden" id="columnFiltersWrap">
<div class="box-header ">
<h3 class="box-title col-md-12"><?= lang('Devices_Filters');?> </h3>
</div>
<!-- Placeholder ------------------------------------------------------- -->
<div id="columnFilters" ></div>
</div>
<!-- datatable ------------------------------------------------------------- -->
<div class="row">
<div class="col-xs-12">
@@ -74,10 +74,13 @@
<!-- box-header -->
<div class="box-header">
<div class=" col-md-9 ">
<div class=" col-sm-8 ">
<h3 id="tableDevicesTitle" class="box-title text-gray "></h3>
</div>
<div class="dummyDevice col-md-3 ">
<div class="dummyDevice col-sm-4 ">
<span id="multiEditPlc">
<!-- multi edit button placeholder -->
</span>
<span>
<a href="deviceDetails.php?mac=new"><i title="<?= lang('Gen_create_new_device');?>" class="fa fa-square-plus"></i> <?= lang('Gen_create_new_device');?></a>
</span>
@@ -106,7 +109,7 @@
<!-- ----------------------------------------------------------------------- -->
</section>
<!-- /.content -->
<div id="multiEditPlc" class="col-md-2"></div>
</div>
<!-- /.content-wrapper -->
@@ -120,7 +123,7 @@
<!-- page script ----------------------------------------------------------- -->
<script>
var deviceStatus = 'all';
var tableRows = getCache ("nax_parTableRows") == "" ? 10 : getCache ("nax_parTableRows") ;
var tableRows = getCache ("nax_parTableRows") == "" ? 20 : getCache ("nax_parTableRows") ;
var tableOrder = getCache ("nax_parTableOrder") == "" ? [[3,'desc'], [0,'asc']] : JSON.parse(getCache ("nax_parTableOrder")) ;
var tableColumnHide = [];
@@ -138,6 +141,8 @@ function main () {
showSpinner();
initFilters();
// render tiles
getDevicesTotals();
@@ -213,7 +218,7 @@ function getDevicesTotals() {
// Attempt to fetch data
$.ajax({
url: '/php/server/query_json.php',
url: 'php/server/query_json.php',
type: "GET",
dataType: "json",
data: {
@@ -324,6 +329,184 @@ function renderInfoboxes(customData) {
}
}
// -----------------------------------------------------------------------------
//Render filters if specified
let columnFilters = [];
function initFilters() {
// Attempt to fetch data
$.ajax({
url: 'php/server/query_json.php',
type: "GET",
dataType: "json",
data: {
file: 'table_devices_filters.json', // Pass the file parameter
nocache: Date.now() // Prevent caching with a timestamp
},
success: function(response) {
if (response && response.data) {
let resultJSON = response.data;
// Save the result to cache
setCache("devicesFilters", JSON.stringify(resultJSON));
// Get the displayed filters from settings
const displayedFilters = createArray(getSetting("UI_columns_filters"));
// Clear any existing filters in the DOM
$('#columnFilters').empty();
console.log(displayedFilters);
// Ensure displayedFilters is an array and not empty
if (Array.isArray(displayedFilters) && displayedFilters.length > 0) {
$('#columnFiltersWrap').removeClass("hidden");
displayedFilters.forEach(columnHeaderStringKey => {
// Get the column name using the mapping function
const columnName = getColumnNameFromLangString(columnHeaderStringKey);
// Ensure columnName is valid before proceeding
if (columnName) {
// Add the filter to the columnFilters array as [columnName, columnHeaderStringKey]
columnFilters.push([columnName, columnHeaderStringKey]);
} else {
console.warn(`Invalid column header string key: ${columnHeaderStringKey}`);
}
});
// Filter resultJSON to include only entries with columnName in columnFilters
resultJSON = resultJSON.filter(entry =>
columnFilters.some(filter => filter[0] === entry.columnName)
);
// Expand resultJSON to include the columnHeaderStringKey
resultJSON.forEach(entry => {
// Find the matching columnHeaderStringKey from columnFilters
const matchingFilter = columnFilters.find(filter => filter[0] === entry.columnName);
// Add the columnHeaderStringKey to the entry
if (matchingFilter) {
entry['columnHeaderStringKey'] = matchingFilter[1];
}
});
console.log(resultJSON);
// Transforming the data
const transformed = {
filters: []
};
// Group data by columnName
resultJSON.forEach(entry => {
const existingFilter = transformed.filters.find(filter => filter.column === entry.columnName);
if (existingFilter) {
// Add the unique columnValue to options if not already present
if (!existingFilter.options.includes(entry.columnValue)) {
existingFilter.options.push(entry.columnValue);
}
} else {
// Create a new filter entry
transformed.filters.push({
column: entry.columnName,
headerKey: entry.columnHeaderStringKey,
options: [entry.columnValue]
});
}
});
// Sort options alphabetically for better readability
transformed.filters.forEach(filter => {
filter.options.sort();
});
// Output the result
transformedJson = transformed
// Process the fetched data
renderFilters(transformedJson);
} else {
console.log("No filters to display.");
}
} else {
console.error("Invalid response format from API");
}
},
error: function(xhr, status, error) {
console.error("Failed to fetch devices data 'table_devices_filters.json':", error);
}
});
}
// -------------------------------------------
// Server side component
function renderFilters(customData) {
// console.log(JSON.stringify(customData));
// Load filter data from the JSON file
$.ajax({
url: 'php/components/devices_filters.php', // PHP script URL
data: { filterObject: JSON.stringify(customData) }, // Send customData as JSON
type: 'POST',
dataType: 'html',
success: function(response) {
// console.log(response);
$('#columnFilters').html(response); // Replace container content with fetched HTML
$('#columnFilters').removeClass('hidden'); // Show the filters container
// Trigger the draw after select change
$('.filter-dropdown').on('change', function() {
// Collect filters
const columnFilters = collectFilters();
// Update DataTable with the new filters or search value (if applicable)
$('#tableDevices').DataTable().draw();
// Optionally, apply column filters (if using filters for individual columns)
const table = $('#tableDevices').DataTable();
table.columnFilters = columnFilters; // Apply your column filters logic
table.draw();
});
},
error: function(xhr, status, error) {
console.error('Error fetching filters:', error);
}
});
}
// -------------------------------------------
// Function to collect filters
function collectFilters() {
const columnFilters = [];
// Loop through each filter group
document.querySelectorAll('.filter-group').forEach(filterGroup => {
const dropdown = filterGroup.querySelector('.filter-dropdown');
if (dropdown) {
const filterColumn = dropdown.getAttribute('data-column');
const filterValue = dropdown.value;
if (filterValue && filterColumn) {
columnFilters.push({
filterColumn: filterColumn,
filterValue: filterValue
});
}
}
});
return columnFilters;
}
// -----------------------------------------------------------------------------
// Map column index to column name for GraphQL query
function mapColumnIndexToFieldName(index, tableColumnVisible) {
@@ -416,8 +599,6 @@ function initializeDatatable (status) {
}
// todo: dynamically filter based on status
var table = $('#tableDevices').DataTable({
"serverSide": true,
"processing": true,
@@ -475,6 +656,12 @@ function initializeDatatable (status) {
console.log(d);
// Handle empty filters
let columnFilters = collectFilters();
if (columnFilters.length === 0) {
columnFilters = [];
}
// Prepare query variables for pagination, sorting, and search
let query = {
@@ -489,7 +676,8 @@ function initializeDatatable (status) {
"order": d.order[0].dir.toUpperCase() // Sort direction (ASC/DESC)
}] : [], // Default to an empty array if no sorting is defined
"search": d.search.value, // Search query
"status": deviceStatus
"status": deviceStatus,
"filters" : columnFilters
}
}
@@ -549,12 +737,13 @@ function initializeDatatable (status) {
},
'paging' : true,
'lengthChange' : true,
'lengthMenu' : [[10, 25, 50, 100, 500, 100000], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
'lengthMenu' : [[10, 20, 25, 50, 100, 500, 100000], [10, 20, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
'searching' : true,
'ordering' : true,
'info' : true,
'autoWidth' : false,
'dom': '<"top"f>rtl<"bottom"ip><"clear">',
// Parameters
'pageLength' : tableRows,
@@ -749,9 +938,9 @@ function initializeDatatable (status) {
// add multi-edit button
$('#multiEditPlc').append(
`<button type="submit" id="multiEdit" class="btn btn-primary" style="display:none" onclick="multiEditDevices();">
<i class="fa fa-pencil pointer" ></i> ${getString("Device_MultiEdit")}
</button>`)
`<span type="submit" id="multiEdit" class="pointer " style="display:none" onclick="multiEditDevices();">
<a href="#"><i class="fa fa-pencil " ></i> ${getString("Device_MultiEdit")} </a>
</span>`)
// Event listener for row selection in DataTable
$('#tableDevices').on('click', 'tr', function (e) {
@@ -799,7 +988,7 @@ function handleLoadingDialog(needsReload = false)
{
// console.log(`needsReload: ${needsReload}`);
$.get('/php/server/query_logs.php?file=execution_queue.log&nocache=' + Date.now(), function(data) {
$.get('php/server/query_logs.php?file=execution_queue.log&nocache=' + Date.now(), function(data) {
if(data.includes("update_api|devices"))
{

View File

@@ -1,70 +0,0 @@
<?php
require 'php/templates/header.php';
?>
<div id="donationsPage" class="content-wrapper">
<!-- Content header--------------------------------------------------------- -->
<section class="content-header">
<h1 id="pageTitle">
<i class="fa fa-heart"></i>
</h1>
</section>
<!-- Main content ---------------------------------------------------------- -->
<section class="content donations">
<div id="donationsText" class="box box-solid"></div>
<div class="content-header">
<h3 class="box-title " id="donationsPlatforms"></h3>
</div>
<div class="box box-solid">
<div class="box-body">
<div class="col-sm-2">
<a target="_blank" href="https://github.com/sponsors/jokob-sk">
<img alt="Sponsor Me on GitHub" src="https://i.imgur.com/X6p5ACK.png" width="150px">
</a>
</div>
<div class="col-sm-2">
<a target="_blank" href="https://www.buymeacoffee.com/jokobsk">
<img alt="Buy Me A Coffee" src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" width="117px" height="30px">
</a>
</div>
<div class="col-sm-2">
<a target="_blank" href="https://www.patreon.com/user?u=84385063">
<img alt="Support me on patreon" src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" width="117px">
</a>
</div>
</div>
</div>
<div class="content-header">
<h3 class="box-title " id="donationsOthers"></h3>
</div>
<div class="box box-solid">
<div class="box-body">
<div class="col-sm-12">
<ul>
<li>Bitcoin: <code>1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM</code></li>
<li>Ethereum: <code>0x6e2749Cb42F4411bc98501406BdcD82244e3f9C7</code></li>
</ul>
</div>
</div>
</div>
<div>
</section>
</div> <!-- End of class="content-wrapper" -->
<script>
function init()
{
$("#donationsText").html(getString("Donations_Text"))
$("#pageTitle").append(getString("Donations_Title"))
$("#donationsPlatforms").append(getString("Donations_Platforms"))
$("#donationsOthers").append(getString("Donations_Others"))
}
init();
</script>
<?php
require 'php/templates/footer.php';
?>

View File

@@ -1,17 +1,3 @@
<!--
#---------------------------------------------------------------------------------#
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# events.php - Front module. Events page #
#---------------------------------------------------------------------------------#
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3 #
# jokob-sk 2022 jokob.sk@gmail.com GNU GPLv3 #
# leiweibau 2022 https://github.com/leiweibau GNU GPLv3 #
# cvc90 2023 https://github.com/cvc90 GNU GPLv3 #
#---------------------------------------------------------------------------------#
-->
<?php
require 'php/templates/header.php';
?>
@@ -19,26 +5,7 @@
<!-- ----------------------------------------------------------------------- -->
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
<!-- Content header--------------------------------------------------------- -->
<section class="content-header">
<h1 id="pageTitle">
<i class="fa fa-bolt"></i>
<?= lang('Events_Title');?>
</h1>
<!-- period selector -->
<span class="breadcrumb" style="top: 0px;">
<select class="form-control" id="period" onchange="javascript: periodChanged();">
<option value="1 day"><?= lang('Events_Periodselect_today');?></option>
<option value="7 days"><?= lang('Events_Periodselect_LastWeek');?></option>
<option value="1 month" selected><?= lang('Events_Periodselect_LastMonth');?></option>
<option value="1 year"><?= lang('Events_Periodselect_LastYear');?></option>
<option value="100 years"><?= lang('Events_Periodselect_All');?></option>
</select>
</span>
</section>
<div class="content-wrapper eventsPage">
<!-- Main content ---------------------------------------------------------- -->
<section class="content">
@@ -123,15 +90,31 @@
<!-- datatable ------------------------------------------------------------- -->
<div class="row">
<div class="col-xs-12">
<div id="tableEventsBox" class="box">
<!-- box-header -->
<div class="box-header">
<h3 id="tableEventsTitle" class="box-title text-gray">Events</h3>
<div class="box-header col-xs-12">
<h3 id="tableEventsTitle" class="box-title text-gray col-xs-10">Events</h3>
<div class="eventsPeriodSelectWrap col-xs-2">
<select class="form-control" id="period" onchange="javascript: periodChanged();">
<option value="1 day"><?= lang('Events_Periodselect_today');?></option>
<option value="7 days"><?= lang('Events_Periodselect_LastWeek');?></option>
<option value="1 month" selected><?= lang('Events_Periodselect_LastMonth');?></option>
<option value="1 year"><?= lang('Events_Periodselect_LastYear');?></option>
<option value="100 years"><?= lang('Events_Periodselect_All');?></option>
</select>
</div>
</div>
<!-- table -->
<div class="box-body table-responsive">
<table id="tableEvents" class="table table-bordered table-hover table-striped ">
<thead>
<tr>

View File

@@ -1,239 +0,0 @@
<?php
require 'php/templates/header.php';
?>
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
<!-- Content header--------------------------------------------------------- -->
<section class="content-header">
<?php require 'php/templates/notification.php'; ?>
<h1 id="pageTitle">
<i class="fa fa-question"></i>
<?= lang('HelpFAQ_Title');?>
</h1>
</section>
<!-- Main content ---------------------------------------------------------- -->
<section class="content">
<h4>
<i class="fa fa-question"></i>
<?= lang('HelpFAQ_Cat_General');?>
</h4>
<div class="panel-group" id="accordion_gen">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse100">
<?= lang('HelpFAQ_Cat_General_100_head');?></a>
</h4>
</div>
<div id="collapse100" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body"><?= lang('HelpFAQ_Cat_General_100_text_a');?>
<span class="text-danger help_faq_code"><?php echo date_default_timezone_get(); ?></span><br>
<?= lang('HelpFAQ_Cat_General_100_text_b');?>
<span class="text-danger help_faq_code"><?php echo php_ini_loaded_file(); ?></span><br>
<?= lang('HelpFAQ_Cat_General_100_text_c');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse101">
<?= lang('HelpFAQ_Cat_General_101_head');?></a>
</h4>
</div>
<div id="collapse101" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_General_101_text');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse102">
<?= lang('HelpFAQ_Cat_General_102_head');?></a>
</h4>
</div>
<div id="collapse102" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_General_102_text');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse102docker">
<?= lang('HelpFAQ_Cat_General_102docker_head');?></a>
</h4>
</div>
<div id="collapse102docker" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_General_102docker_text');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse103">
<?= lang('HelpFAQ_Cat_General_103_head');?></a>
</h4>
</div>
<div id="collapse103" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_General_103_text');?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_net" href="#collapse601">
<?= lang('HelpFAQ_Cat_Network_601_head');?></a>
</h4>
</div>
<div id="collapse601" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Network_601_text');?>
</div>
</div>
</div>
</div>
</div>
<h4>
<i class="fa fa-laptop"></i>
<?= lang('Navigation_Devices');?>
</h4>
<div class="panel-group" id="accordion_dev">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_dev" href="#collapse200">
<?= lang('HelpFAQ_Cat_Device_200_head');?></a>
</h4>
</div>
<div id="collapse200" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Device_200_text');?>
</div>
</div>
</div>
</div>
<h4>
<i class="fa fa-info-circle"></i><?= lang('HelpFAQ_Cat_Detail');?></h4>
<div class="panel-group" id="accordion_det">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse300">
<?= lang('HelpFAQ_Cat_Detail_300_head');?> "<?= lang('DevDetail_MainInfo_Network');?>" / "<?= lang('DevDetail_MainInfo_Network_Port');?>"?</a>
</h4>
</div>
<div id="collapse300" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
"<?= lang('DevDetail_MainInfo_Network');?>" <?= lang('HelpFAQ_Cat_Detail_300_text_a');?><br>
"<?= lang('DevDetail_MainInfo_Network_Port');?>" <?= lang('HelpFAQ_Cat_Detail_300_text_b');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse302">
<?= lang('HelpFAQ_Cat_Detail_302_head_a');?> "<?= lang('DevDetail_EveandAl_RandomMAC');?>" <?= lang('HelpFAQ_Cat_Detail_302_head_b');?></a>
</h4>
</div>
<div id="collapse302" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Detail_302_text');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse303">
<?= lang('HelpFAQ_Cat_Detail_303_head');?></a>
</h4>
</div>
<div id="collapse303" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Detail_303_text');?>
</div>
</div>
</div>
</div>
<h4>
<i class="fa fa-calendar"></i>
<?= lang('Navigation_Presence');?>
</h4>
<div class="panel-group" id="accordion_pre">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_pre" href="#collapse400">
<?= lang('HelpFAQ_Cat_Presence_400_head');?></a>
</h4>
</div>
<div id="collapse400" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Presence_400_text');?>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_pre" href="#collapse401">
<?= lang('HelpFAQ_Cat_Presence_401_head');?></a>
</h4>
</div>
<div id="collapse401" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Presence_401_text');?>
</div>
</div>
</div>
</div>
<h4>
<i class="fa fa-network-wired"></i><?= lang('Navigation_Network');?></h4>
<div class="panel-group" id="accordion_net">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion_net" href="#collapse600">
<?= lang('HelpFAQ_Cat_Network_600_head');?></a>
</h4>
</div>
<div id="collapse600" class="panel-collapse collapse" style="font-size: 16px;">
<div class="panel-body">
<?= lang('HelpFAQ_Cat_Network_600_text');?>
</div>
</div>
</div>
</section>
<br>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
<!-- ----------------------------------------------------------------------- -->
<?php
require 'php/templates/footer.php';
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
front/img/netalertx_docs.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

377
front/img/svg/netalertx_docs.svg Executable file
View File

@@ -0,0 +1,377 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 52.916667 52.916668"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
sodipodi:docname="netalertx_docs.svg"
inkscape:export-filename="C:\Users\jokob\netalertx_docs.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2.8284271"
inkscape:cx="72.124892"
inkscape:cy="128.33988"
inkscape:window-width="3378"
inkscape:window-height="1417"
inkscape:window-x="54"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer6"
units="px"
width="50px" />
<defs
id="defs2">
<inkscape:path-effect
effect="powermask"
id="path-effect51283"
is_visible="true"
lpeversion="1"
uri="#mask-powermask-path-effect51283"
invert="false"
hide_mask="false"
background="true"
background_color="#ffffffff" />
<inkscape:path-effect
effect="powermask"
id="path-effect51278"
is_visible="true"
lpeversion="1"
uri="#mask-powermask-path-effect51278"
invert="false"
hide_mask="false"
background="true"
background_color="#ffffffff" />
<inkscape:path-effect
effect="powermask"
id="path-effect51273"
is_visible="true"
lpeversion="1"
uri="#mask-powermask-path-effect51273"
invert="false"
hide_mask="false"
background="true"
background_color="#ffffffff" />
<inkscape:path-effect
effect="powermask"
id="path-effect48754"
is_visible="true"
lpeversion="1"
uri="#mask-powermask-path-effect48754"
invert="false"
hide_mask="false"
background="true"
background_color="#ffffffff" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath48972">
<path
style="fill:#000000;stroke-width:0.280643"
id="path48974"
width="56.128242"
height="56.128246"
x="-18.924671"
y="-56.198174"
transform="rotate(45.438374)"
mask="none"
sodipodi:type="rect" />
</clipPath>
<mask
maskUnits="userSpaceOnUse"
id="mask49405">
<text
xml:space="preserve"
style="font-size:60.8695px;line-height:1.25;font-family:Amiri;-inkscape-font-specification:Amiri;display:inline;stroke-width:1.52174"
x="66.930733"
y="78.642288"
id="text49409"
transform="scale(1.4861626,0.67287388)"><tspan
sodipodi:role="line"
id="tspan49407"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Tw Cen MT';-inkscape-font-specification:'Tw Cen MT';fill:#ffffff;stroke-width:1.52174"
x="66.930733"
y="78.642288">A</tspan></text>
</mask>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath50306">
<circle
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
id="circle50308"
cy="26.458334"
cx="26.458334"
r="26.458334"
clip-path="url(#clipPath48972)"
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath48972-7">
<path
style="fill:#000000;stroke-width:0.280643"
id="path48974-5"
width="56.128242"
height="56.128246"
x="-18.924671"
y="-56.198174"
transform="rotate(45.438374)"
mask="none"
sodipodi:type="rect" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath50306-6">
<circle
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
id="circle50308-5"
cy="26.458334"
cx="26.458334"
r="26.458334"
clip-path="url(#clipPath48972)"
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
</clipPath>
<mask
maskUnits="userSpaceOnUse"
id="mask-powermask-path-effect51273">
<path
id="mask-powermask-path-effect51273_box"
style="fill:#ffffff;fill-opacity:1"
d="m 71.788348,33.677177 h 2.00083 v 2.173766 h -2.00083 z" />
<path
style="fill:#000000"
id="path51263"
sodipodi:type="arc"
sodipodi:cx="66.211845"
sodipodi:cy="37.490814"
sodipodi:rx="3.9464016"
sodipodi:ry="1.4616301"
sodipodi:start="0"
sodipodi:end="0.031086059"
sodipodi:open="true"
sodipodi:arc-type="arc"
d="m 70.158247,37.490814 a 3.9464016,1.4616301 0 0 1 -0.0019,0.04543" />
</mask>
<mask
maskUnits="userSpaceOnUse"
id="mask-powermask-path-effect51278">
<path
style="fill:#000000"
id="path51267"
sodipodi:type="arc"
sodipodi:cx="66.211845"
sodipodi:cy="37.490814"
sodipodi:rx="3.9464016"
sodipodi:ry="1.4616301"
sodipodi:start="0"
sodipodi:end="0.031086059"
sodipodi:open="true"
sodipodi:arc-type="arc" />
</mask>
<mask
maskUnits="userSpaceOnUse"
id="mask-powermask-path-effect51283">
<path
style="fill:#000000"
id="path51271"
sodipodi:type="arc"
sodipodi:cx="66.211845"
sodipodi:cy="37.490814"
sodipodi:rx="3.9464016"
sodipodi:ry="1.4616301"
sodipodi:start="0"
sodipodi:end="0.031086059"
sodipodi:open="true"
sodipodi:arc-type="arc" />
</mask>
<filter
id="mask-powermask-path-effect51273_inverse"
inkscape:label="filtermask-powermask-path-effect51273"
style="color-interpolation-filters:sRGB"
height="100"
width="100"
x="-50"
y="-50">
<feColorMatrix
id="mask-powermask-path-effect51273_primitive1"
values="1"
type="saturate"
result="fbSourceGraphic" />
<feColorMatrix
id="mask-powermask-path-effect51273_primitive2"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
in="fbSourceGraphic" />
</filter>
</defs>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Red 1"
style="display:none">
<circle
style="fill:#ff2a2a;stroke-width:0.176318"
id="path31-8"
cy="26.458334"
cx="26.458334"
r="26.458334" />
</g>
<g
inkscape:label="Black"
inkscape:groupmode="layer"
id="layer1"
style="display:inline">
<ellipse
style="fill:#000000;stroke-width:0.176146"
id="path31"
cy="26.51001"
cx="26.458334"
rx="26.458334"
ry="26.406658" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="A - Layer 2"
style="display:none">
<rect
style="fill:#ffffff;stroke-width:0.328992"
id="rect48998"
width="26.0966"
height="6.0620313"
x="13.255443"
y="41.262722" />
</g>
<g
inkscape:groupmode="layer"
id="g48055"
inkscape:label="Red top"
style="display:none;mix-blend-mode:normal">
<circle
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
id="circle48752"
cy="26.458334"
cx="26.458334"
r="26.458334"
clip-path="url(#clipPath48972)"
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
<ellipse
style="display:inline;mix-blend-mode:normal;fill:#000000;stroke-width:0.43638"
id="path50080"
clip-path="url(#clipPath50306)"
ry="13.739323"
rx="16.735666"
cy="22.874514"
cx="26.36149"
transform="translate(0,0.09980904)" />
<path
style="fill:#000000"
id="path51325"
sodipodi:type="arc"
sodipodi:cx="16.772207"
sodipodi:cy="26.090099"
sodipodi:rx="4.1291056"
sodipodi:ry="7.6004772"
sodipodi:start="0"
sodipodi:end="0.031086059"
sodipodi:arc-type="slice"
d="m 20.901313,26.090099 a 4.1291056,7.6004772 0 0 1 -0.002,0.236231 l -4.127111,-0.236231 z" />
<path
style="fill:#d40000"
id="path51717"
sodipodi:type="arc"
sodipodi:cx="26.441042"
sodipodi:cy="-26.531424"
sodipodi:rx="10.418671"
sodipodi:ry="9.5820541"
sodipodi:start="0.82219863"
sodipodi:end="2.3054129"
sodipodi:arc-type="slice"
d="m 33.532115,-19.511189 a 10.418671,9.5820541 0 0 1 -14.074736,0.09049 l 6.983663,-7.110726 z"
transform="matrix(1,0,0.0048047,-0.99998846,0,0)" />
<path
style="fill:#ffffff;stroke-width:0.276214"
d="M 145.28835,50.354872 C 127.01317,34.62734 98.057144,30.012421 73.710372,38.947003 c -6.518003,2.391924 -14.288822,6.834002 -19.265958,11.01311 -1.198654,1.006465 -2.270358,1.829935 -2.381565,1.829935 -0.111206,0 -5.210052,-5.102002 -11.33077,-11.337781 L 29.603503,29.114489 30.822139,27.851613 c 0.670251,-0.69458 2.51592,-2.384634 4.101489,-3.755674 C 50.725112,10.43241 69.462577,2.3767456 90.736164,0.10085492 95.380582,-0.39601422 106.33043,-0.31105699 111.03786,0.25837091 133.04363,2.9202648 151.46536,11.26468 167.83762,25.986722 l 3.30701,2.97369 -2.29392,2.320103 c -1.26165,1.276057 -6.58213,6.517685 -11.82329,11.648065 l -9.52936,9.327957 z"
id="path52311"
transform="scale(0.26458333)" />
<path
style="fill:#ffffff;stroke-width:0.276214"
d="M 86.538548,86.634546 74.145111,73.25799 74.899337,72.758689 c 4.93766,-3.268754 10.138703,-6.508578 16.602198,-7.437693 5.484021,-0.788317 12.228205,-0.984814 16.377135,-0.09119 6.77689,1.459652 11.87156,4.340971 17.02452,7.792011 l 0.97468,0.652765 -1.37124,1.269268 c -0.86863,0.804036 -6.82647,6.676301 -13.34742,13.259175 L 99.423152,99.796276 Z"
id="path52350"
transform="scale(0.26458333)"
inkscape:export-filename="C:\Users\jokob\path52350.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
sodipodi:nodetypes="ccsssscsscc" />
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="Circle"
style="display:inline">
<path
style="fill:#000000"
id="path50026"
sodipodi:type="arc"
sodipodi:cx="71.071762"
sodipodi:cy="34.677177"
sodipodi:rx="1.7174155"
sodipodi:ry="5.5907354"
sodipodi:start="0"
sodipodi:end="0.031086059"
sodipodi:open="true"
sodipodi:arc-type="arc"
mask="url(#mask-powermask-path-effect51273)"
d="m 72.789178,34.677177 a 1.7174155,5.5907354 0 0 1 -8.3e-4,0.173766"
inkscape:path-effect="#path-effect51273" />
<path
style="fill:#d40000;stroke-width:0.276214"
d="M 86.416478,86.793237 C 73.427951,73.815968 73.387119,73.801376 73.387119,73.801376 c 3.874197,-3.341721 11.025508,-6.981646 17.312424,-8.529335 2.339787,-0.576001 4.881362,-1.25628 8.810591,-1.259564 4.438736,-0.0037 8.292516,0.857843 13.253396,2.535104 4.59135,1.552325 7.8315,3.224336 11.49958,5.934101 l 1.61476,1.192897 -2.31005,2.336325 c -1.27053,1.284978 -7.22284,7.16236 -13.22736,13.060849 L 99.423152,99.796276 C 95.128284,95.409033 87.282899,87.658907 86.416478,86.793237 Z"
id="path52465"
transform="scale(0.26458333)"
sodipodi:nodetypes="sssssscsscs" />
<path
style="fill:#d40000;stroke-width:0.074168"
d="M 38.412677,13.39572 C 34.322163,9.945267 28.437517,8.4874766 22.684204,9.4993379 19.419721,10.073478 16.752307,11.410793 13.835187,13.872492 l -0.14691,0.126732 -0.587936,-0.661605 c -0.268568,-0.30222 -1.619514,-1.65761 -2.963235,-3.048642 L 7.7265561,7.8632145 7.9975963,7.5868118 C 9.8344314,5.713635 13.005888,3.476019 15.380049,2.3878744 20.659765,-0.03196726 26.24205,-0.73479764 31.856076,0.42838695 36.599757,1.4112419 40.746004,3.5106537 44.46876,7.1557672 l 0.709881,0.6950753 -0.663694,0.69037 C 44.080041,8.9935983 42.672626,10.391271 41.3963,11.655819 L 39.075708,13.955 Z"
id="path52504"
inkscape:export-filename="C:\Users\jokob\path52504.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
sodipodi:nodetypes="ssscsccsssscsscs" />
<rect
style="fill:#ffffff;stroke-width:0.270734"
id="rect9599"
width="8.0679188"
height="21.176973"
x="22.265251"
y="30.578777" />
<path
style="fill:#ffffff;fill-opacity:1;stroke-width:0.353553"
d="m 86.613132,86.61313 -12.851203,-12.854821 0.86086,-0.706098 c 1.692083,-1.387887 6.387757,-3.998693 9.623614,-5.350752 7.33291,-3.063958 14.480764,-4.12547 20.582177,-3.056613 3.69356,0.647044 9.99695,2.663626 13.06868,4.180934 2.21267,1.092967 7.61419,4.559526 7.61419,4.886591 0,0.102465 -5.8606,5.939388 -13.02356,12.97094 L 99.464335,99.467952 Z"
id="path13796"
transform="scale(0.26458333)" />
<path
style="fill:#ffffff;fill-opacity:1;stroke-width:0.353553"
d="M 40.562149,41.010783 29.328726,29.577286 33.137528,26.202177 C 50.057066,11.209199 68.487351,2.8161465 89.979339,0.31672328 96.591211,-0.45220831 108.48969,-0.19409453 115.05495,0.86068879 135.48174,4.1424805 152.54396,12.522653 167.06663,26.406419 l 3.39168,3.242463 -11.39113,11.395174 -11.39113,11.395178 -2.86219,-2.330889 C 131.23238,39.047901 112.18782,33.324108 93.81593,34.781043 78.86759,35.966481 67.456828,40.362971 55.747418,49.448575 54.209095,50.642196 52.690616,51.804531 52.37302,52.031537 51.87959,52.384228 50.161133,50.780729 40.562149,41.010783 Z"
id="path13835"
transform="scale(0.26458333)"
inkscape:export-filename="C:\Users\jokob\docs.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -92,10 +92,8 @@ if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
<!-- iCheck -->
<link rel="stylesheet" href="lib/iCheck/square/blue.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="lib/font-awesome/fontawesome.min.css">
<link rel="stylesheet" href="lib/font-awesome/solid.css">
<link rel="stylesheet" href="lib/font-awesome/brands.css">
<link rel="stylesheet" href="lib/font-awesome/v5-font-face.css">
<link rel="stylesheet" href="lib/font-awesome/all.min.css">
<!-- Favicon -->
<link id="favicon" rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
@@ -112,7 +110,7 @@ switch ($UI_THEME) {
?>
<link rel="stylesheet" href="/css/offline-font.css">
</head>
<body class="hold-transition login-page">
<body class="hold-transition login-page col-sm-12 col-sx-12">
<div class="login-box login-custom">
<div class="login-logo">
<a href="/index2.php">Net<b>Alert</b><sup>x</sup></a>

View File

@@ -115,9 +115,9 @@ function cacheSettings()
return new Promise((resolve, reject) => {
if(!getCache('completedCalls').includes('cacheSettings'))
{
$.get('/php/server/query_json.php', { file: 'table_settings.json', nocache: Date.now() }, function(resSet) {
$.get('php/server/query_json.php', { file: 'table_settings.json', nocache: Date.now() }, function(resSet) {
$.get('/php/server/query_json.php', { file: 'plugins.json', nocache: Date.now() }, function(resPlug) {
$.get('php/server/query_json.php', { file: 'plugins.json', nocache: Date.now() }, function(resPlug) {
pluginsData = resPlug["data"];
settingsData = resSet["data"];
@@ -225,7 +225,7 @@ function cacheStrings() {
});
// Fetch strings and translations from plugins
$.get('/php/server/query_json.php', { file: 'table_plugins_language_strings.json', nocache: Date.now() })
$.get('php/server/query_json.php', { file: 'table_plugins_language_strings.json', nocache: Date.now() })
.done((pluginRes) => {
const data = pluginRes["data"];
@@ -737,7 +737,7 @@ function forceLoadUrl(relativeUrl) {
// -----------------------------------------------------------------------------
function navigateToDeviceWithIp (ip) {
$.get('/php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(res) {
$.get('php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(res) {
devices = res["data"];
@@ -776,6 +776,11 @@ function checkMacOrInternet(inputStr) {
}
}
// Alias
function isValidMac(value) {
return checkMacOrInternet(value);
}
// -----------------------------------------------------------------------------
// Gte MAC from query string
function getMac(){
@@ -959,7 +964,7 @@ function cacheDevices()
// if(!getCache('completedCalls').includes('cacheDevices'))
// {
$.get('/php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(data) {
$.get('php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(data) {
// console.log(data)
@@ -1298,6 +1303,38 @@ $(document).ready(function() {
}
});
// -----------------------------------------------------------
// Restart Backend Python Server
function askRestartBackend() {
// Ask
showModalWarning(getString('Maint_RestartServer'), getString('Maint_Restart_Server_noti_text'),
getString('Gen_Cancel'), getString('Maint_RestartServer'), 'restartBackend');
}
// -----------------------------------------------------------
function restartBackend() {
modalEventStatusId = 'modal-message-front-event'
// Execute
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: "addToExecutionQueue", action: `${getGuid()}|cron_restart_backend` },
success: function(data, textStatus) {
// showModalOk ('Result', data );
// show message
showModalOk(getString("general_event_title"), `${getString("general_event_description")} <br/> <br/> <code id='${modalEventStatusId}'></code>`);
updateModalState()
write_notification('[Maintenance] App manually restarted', 'info')
}
})
}
// -----------------------------------------------------------------------------
// initialize
// -----------------------------------------------------------------------------
@@ -1325,7 +1362,7 @@ function clearCache() {
// -----------------------------------------------------------------------------
// Function to check if cache needs to be refreshed because of setting changes
function checkSettingChanges() {
$.get('/php/server/query_json.php', { file: 'app_state.json', nocache: Date.now() }, function(appState) {
$.get('php/server/query_json.php', { file: 'app_state.json', nocache: Date.now() }, function(appState) {
const importedMilliseconds = parseInt(appState["settingsImported"] * 1000);
const lastReloaded = parseInt(sessionStorage.getItem(sessionStorageKey + '_time'));
@@ -1380,7 +1417,7 @@ async function waitForGraphQLServer() {
// Returns 1 if running, 0 otherwise
async function isGraphQLServerRunning() {
try {
const response = await $.get('/php/server/query_json.php', { file: 'app_state.json', nocache: Date.now()});
const response = await $.get('php/server/query_json.php', { file: 'app_state.json', nocache: Date.now()});
console.log("graphQLServerStarted: " + response["graphQLServerStarted"]);
setCache("graphQLServerStarted", response["graphQLServerStarted"]);
return response["graphQLServerStarted"];

View File

@@ -85,7 +85,7 @@ function renderList(
// Check if database is locked
function checkDbLock() {
$.ajax({
url: "/php/server/query_logs.php?file=db_is_locked.log",
url: "php/server/query_logs.php?file=db_is_locked.log",
type: "GET",
success: function (response) {

View File

@@ -68,11 +68,13 @@ function showModalWarning(
callbackFunction = null,
triggeredBy = null
) {
prefix = "modal-warning";
// set captions
$("#modal-warning-title").html(title);
$("#modal-warning-message").html(message);
$("#modal-warning-cancel").html(btnCancel);
$("#modal-warning-OK").html(btnOK);
$(`#${prefix}-title`).html(title);
$(`#${prefix}-message`).html(message);
$(`#${prefix}-cancel`).html(btnCancel);
$(`#${prefix}-OK`).html(btnOK);
if (callbackFunction != null) {
modalCallbackFunction = callbackFunction;
@@ -83,7 +85,7 @@ function showModalWarning(
}
// Show modal
$("#modal-warning").modal("show");
$(`#${prefix}`).modal("show");
}
// -----------------------------------------------------------------------------
@@ -93,7 +95,8 @@ function showModalInput(
btnCancel = getString("Gen_Cancel"),
btnOK = getString("Gen_Okay"),
callbackFunction = null,
triggeredBy = null
triggeredBy = null,
defaultValue = ""
) {
prefix = "modal-input";
@@ -102,6 +105,7 @@ function showModalInput(
$(`#${prefix}-message`).html(message);
$(`#${prefix}-cancel`).html(btnCancel);
$(`#${prefix}-OK`).html(btnOK);
$(`#${prefix}-textarea`).val(defaultValue);
if (callbackFunction != null) {
modalCallbackFunction = callbackFunction;
@@ -310,7 +314,6 @@ function checkNotification() {
if(response != "[]")
{
// Find the oldest unread notification with level "interrupt"
const oldestInterruptNotification = response.find(notification => notification.read === 0 && notification.level === "interrupt");
const allUnreadNotification = response.filter(notification => notification.read === 0 && notification.level === "alert");
@@ -322,6 +325,9 @@ function checkNotification() {
const decodedContent = safeDecodeURIComponent(oldestInterruptNotification.content);
// only check and display modal if no modal currently displayed to prevent looping
if($("#modal-ok").is(":visible") == false)
{
showModalOK("Notification", decodedContent, function() {
// Mark the notification as read
$.ajax({
@@ -346,10 +352,9 @@ function checkNotification() {
});
});
}
}
handleUnreadNotifications(allUnreadNotification.length)
}
},
error: function() {

View File

@@ -717,6 +717,7 @@ const handleElementOptions = (setKey, elementOptions, transformers, val) => {
let customParams = "";
let customId = "";
let columns = [];
let base64Regex = "";
elementOptions.forEach((option) => {
@@ -773,6 +774,9 @@ const handleElementOptions = (setKey, elementOptions, transformers, val) => {
if (option.columns) {
columns = option.columns;
}
if (option.base64Regex) {
base64Regex = option.base64Regex;
}
});
if (transformers.includes("sha256")) {
@@ -796,7 +800,8 @@ const handleElementOptions = (setKey, elementOptions, transformers, val) => {
onChange,
customParams,
customId,
columns
columns,
base64Regex
};
};
@@ -973,7 +978,8 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
onChange,
customParams,
customId,
columns
columns,
base64Regex
} = handleElementOptions(setKey, elementOptions, transformers, inVal);
// Override value
@@ -1022,6 +1028,7 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
my-customparams="${customParams}"
my-customid="${customId}"
my-originalSetKey="${originalSetKey}"
my-base64Regex="${base64Regex}"
id="${setKey}${suffix}"
type="${inputType}"
value="${val}"

View File

@@ -171,7 +171,46 @@ function updateIconPreview(elem) {
tryUpdateIcon();
}
// ----------------------------------------------
// Validate the value based on regex
// ⚠ IMPORTANT: use the below to get a valid REGEX ⚠
// const regexStr = String.raw`^(?:\*|(?:[0-9]|[1-5][0-9]|[0-9]+-[0-9]+|\*/[0-9]+))\s+(?:\*|(?:[0-9]|1[0-9]|2[0-3]|[0-9]+-[0-9]+|\*/[0-9]+))\s+(?:\*|(?:[1-9]|[12][0-9]|3[01]|[0-9]+-[0-9]+|\*/[0-9]+))\s+(?:\*|(?:[1-9]|1[0-2]|[0-9]+-[0-9]+|\*/[0-9]+))\s+(?:\*|(?:[0-6]|[0-6]-[0-6]|\*/[0-9]+))$`;
// console.log(btoa(regexStr));
function validateRegex(elem) {
const iconSpan = $(elem).parent().find(".validityCheck");
const inputElem = $(elem);
const regexTmp = atob($(inputElem).attr("my-base64Regex")); // Decode base64 regex
const regex = new RegExp(regexTmp); // Convert to a valid RegExp object
let attempts = 0;
function tryUpdateValidityResultIcon() {
let value = inputElem.val().trim(); // Ensure trimmed value
if (value === "") {
attempts++;
if (attempts < 10) {
setTimeout(tryUpdateValidityResultIcon, 1000); // Retry after 1 sec if empty
} else {
console.error("Input value is empty after 10 attempts");
}
return;
}
// Validate against regex
if (regex.test(value)) {
iconSpan.html("<i class='fa-regular fa-check'></i>");
} else {
iconSpan.html("<i class='fa-regular fa-xmark'></i>");
}
}
// Attach real-time validation on input change
inputElem.on("input", tryUpdateValidityResultIcon);
tryUpdateValidityResultIcon(); // Initial validation
}
// -----------------------------------------------------------------------------
// Nice checkboxes with iCheck
@@ -231,38 +270,65 @@ function copyToClipboard(buttonElement) {
// Simple Sortable Table columns
// -----------------------------------------------------------------------------
// Function to handle column sorting when a user clicks on a table header
function sortColumn(element) {
var th = $(element).closest('th');
var table = th.closest('table');
var columnIndex = th.index();
var ascending = !th.data('asc');
var th = $(element).closest('th'); // Get the clicked table header
var table = th.closest('table'); // Find the closest table
var columnIndex = th.index(); // Get the index of the column
var ascending = !th.data('asc'); // Toggle sorting order
sortTable(table, columnIndex, ascending);
th.data('asc', ascending);
th.data('asc', ascending); // Store sorting order
}
// Function to sort the table based on the selected column
function sortTable(table, columnIndex, ascending) {
var tbody = table.find('tbody');
var rows = tbody.find('tr').toArray().sort(comparer(columnIndex));
var tbody = table.find('tbody'); // Get the table body
var rows = tbody.find('tr').toArray().sort(comparer(columnIndex)); // Convert rows to an array and sort
if (!ascending) {
rows = rows.reverse();
rows = rows.reverse(); // Reverse order if descending
}
for (var i = 0; i < rows.length; i++) {
tbody.append(rows[i]);
tbody.append(rows[i]); // Append sorted rows back to the table
}
}
// Function to compare values in the selected column
function comparer(index) {
return function (a, b) {
var valA = getCellValue(a, index);
var valB = getCellValue(b, index);
return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB);
// Check if both values are valid IP addresses, and sort numerically if so
if (isIPAddress(valA) && isIPAddress(valB)) {
return ipToNum(valA) - ipToNum(valB);
}
// If both values are numbers, sort numerically
if ($.isNumeric(valA) && $.isNumeric(valB)) {
return valA - valB;
}
// Otherwise, sort as text
return valA.localeCompare(valB);
};
}
// Function to get the text value from a table cell
function getCellValue(row, index) {
return $(row).children('td').eq(index).text();
return $(row).children('td').eq(index).text().trim(); // Get text from the specified column and trim spaces
}
// Function to check if a string is a valid IPv4 address
function isIPAddress(value) {
return /^\d{1,3}(\.\d{1,3}){3}$/.test(value); // Regular expression to match IPv4 format
}
// Function to convert an IP address to a numeric value for sorting
function ipToNum(ip) {
return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0);
}
// -----------------------------------------------------------------------------
// handling events
// -----------------------------------------------------------------------------
@@ -356,7 +422,7 @@ function updateModalState() {
setTimeout(function() {
// Fetch the content from the log file using an AJAX request
$.ajax({
url: '/php/server/query_logs.php?file=execution_queue.log',
url: 'php/server/query_logs.php?file=execution_queue.log',
type: 'GET',
success: function(data) {
// Update the content of the HTML element (e.g., a div with id 'logContent')
@@ -508,8 +574,52 @@ function showIconSelection() {
}
// "Device_TableHead_Owner",
// "Device_TableHead_Type",
// "Device_TableHead_Group",
// "Device_TableHead_Status",
// "Device_TableHead_Location",
// "Device_TableHead_Vendor",
// "Device_TableHead_SyncHubNodeName",
// "Device_TableHead_NetworkSite",
// "Device_TableHead_SSID",
// "Device_TableHead_SourcePlugin"
// -----------------------------------------------------------------------------
// Get teh correct db column code name based on table header title string
function getColumnNameFromLangString(headStringKey) {
columnNameMap = {
"Device_TableHead_Name": "devName",
"Device_TableHead_Owner": "devOwner",
"Device_TableHead_Type": "devType",
"Device_TableHead_Icon": "devIcon",
"Device_TableHead_Favorite": "devFavorite",
"Device_TableHead_Group": "devGroup",
"Device_TableHead_FirstSession": "devFirstConnection",
"Device_TableHead_LastSession": "devLastConnection",
"Device_TableHead_LastIP": "devLastIP",
"Device_TableHead_MAC": "devMac",
"Device_TableHead_Status": "devStatus",
"Device_TableHead_MAC_full": "devMac",
"Device_TableHead_LastIPOrder": "devIpLong",
"Device_TableHead_Rowid": "rowid",
"Device_TableHead_Parent_MAC": "devParentMAC",
"Device_TableHead_Connected_Devices": "devParentChildrenCount",
"Device_TableHead_Location": "devLocation",
"Device_TableHead_Vendor": "devVendor",
"Device_TableHead_Port": "devParentPort",
"Device_TableHead_GUID": "devGUID",
"Device_TableHead_SyncHubNodeName": "devSyncHubNode",
"Device_TableHead_NetworkSite": "devSite",
"Device_TableHead_SSID": "devSSID",
"Device_TableHead_SourcePlugin": "devSourcePlugin",
"Device_TableHead_PresentLastScan": "devPresentLastScan",
"Device_TableHead_AlertDown": "devAlertDown",
"Device_TableHead_CustomProps": "devCustomProps"
};
return columnNameMap[headStringKey] || "";
}
// -----------------------------------------------------------------------------

9
front/lib/font-awesome/all.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,19 +0,0 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:root, :host {
--fa-style-family-classic: 'Font Awesome 6 Free';
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
@font-face {
font-family: 'Font Awesome 6 Free';
font-style: normal;
font-weight: 900;
font-display: block;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
.fas,
.fa-solid {
font-weight: 900; }

View File

@@ -1,6 +0,0 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}

View File

@@ -1,22 +0,0 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face {
font-family: 'Font Awesome 5 Brands';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 900;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }

View File

@@ -1,6 +0,0 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}

4178
front/lib/treeviz/bundle.js Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More