Compare commits

..

249 Commits

Author SHA1 Message Date
Anonymous
c570ff1d1c Translated using Weblate (Russian)
Currently translated at 99.2% (654 of 659 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-04-17 11:32:58 +02:00
Anonymous
c462a83c3d Translated using Weblate (Spanish)
Currently translated at 99.2% (654 of 659 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-04-17 11:32:57 +02:00
jokob-sk
81a2f34731 Weblate 2024-04-17 19:32:12 +10:00
jokob-sk
af9ce3bb55 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-17 19:20:38 +10:00
jokob-sk
f2593a113b Footer tweaks 2024-04-17 19:20:31 +10:00
Safeguard
4e376aad73 Translated using Weblate (Russian)
Currently translated at 99.6% (655 of 657 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-04-17 06:50:13 +02:00
github-actions[bot]
dbf0e3f777 [🤖Automation] Update README with sponsors information 2024-04-16 11:53:49 +00:00
jokob-sk
a21ac1fab3 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-15 22:10:23 +10:00
jokob-sk
796413429b Logo tweaks 2024-04-15 22:10:05 +10:00
github-actions[bot]
27b4349ec8 [🤖Automation] Update README with sponsors information 2024-04-15 11:53:39 +00:00
jokob-sk
a1b025d461 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-15 20:51:26 +10:00
jokob-sk
9f1247141e More icons work - default icon fix🔨 2024-04-15 20:51:17 +10:00
github-actions[bot]
72cec47e11 [🤖Automation] Update README with sponsors information 2024-04-14 14:33:42 +00:00
jokob-sk
b55bab964e More icons work - lang fix🔨 2024-04-14 12:39:41 +10:00
jokob-sk
da171f6d3c More icons work - lang🔨 2024-04-14 12:36:28 +10:00
jokob-sk
8e7e437b4c More icons work 🔨 2024-04-14 12:34:14 +10:00
jokob-sk
d75f27c6db Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-14 09:52:14 +10:00
jokob-sk
1779da3be0 CSS icon button fix #629 & DB fucntion test 2024-04-14 09:52:00 +10:00
github-actions[bot]
17ab77e78f [🤖Automation] Update README with sponsors information 2024-04-13 11:53:59 +00:00
jokob-sk
ed983279d5 Filter applied on <> arrows #627 2024-04-13 12:58:10 +10:00
jokob-sk
e7ce7513ae IP address not updated when <> used #626 2024-04-13 12:02:10 +10:00
jokob-sk
ae0ba6ed8f Merge pull request #625 from vladaurosh/main
Update Dockerfile with nmap-scripts
2024-04-13 10:12:40 +10:00
vladaurosh
6700565c8b Update Dockerfile
Adding nmap-scripts package to fix https://github.com/jokob-sk/NetAlertX/issues/623
2024-04-13 01:07:02 +01:00
jokob-sk
efeb15de76 CLI small refactor 2024-04-13 09:10:29 +10:00
jokob-sk
30c7035f30 ALWAYS_FRESH_INSTALL account for old dir location 2024-04-13 08:50:41 +10:00
jokob-sk
7fb4db01e7 Weblate 2024-04-13 08:42:01 +10:00
Anonymous
98080fba9f Translated using Weblate (Italian)
Currently translated at 0.1% (1 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2024-04-13 00:39:34 +02:00
Safeguard
db3539615f Translated using Weblate (Russian)
Currently translated at 98.7% (648 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-04-13 00:39:30 +02:00
Anonymous
77bff384b8 Translated using Weblate (Norwegian Bokmål)
Currently translated at 1.6% (11 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2024-04-13 00:39:29 +02:00
Gooseman
a7abd31f77 Translated using Weblate (French)
Currently translated at 45.2% (297 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2024-04-13 00:39:13 +02:00
gallegonovato
bc7e3519e1 Translated using Weblate (Spanish)
Currently translated at 99.8% (655 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-04-13 00:39:12 +02:00
Anonymous
d10c60f569 Translated using Weblate (German)
Currently translated at 87.8% (576 of 656 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-04-13 00:39:12 +02:00
jokob-sk
7b714064bb Moving of report templates 2024-04-13 08:37:00 +10:00
jokob-sk
b977781937 Fresh install fixes 2024-04-13 07:13:09 +10:00
jokob-sk
ee90897208 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-13 06:48:49 +10:00
jokob-sk
121178452f Missing app.log init 2024-04-13 06:48:29 +10:00
github-actions[bot]
421d5129ff [🤖Automation] Update README with sponsors information 2024-04-12 11:53:43 +00:00
jokob-sk
8579b010c6 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-12 21:32:02 +10:00
jokob-sk
0d20562930 New logo 2024-04-12 21:31:38 +10:00
Hosted Weblate
63b3c4eadb Merge branch 'origin/main' into Weblate. 2024-04-12 11:47:37 +02:00
Anonymous
b2185f48a7 Translated using Weblate (Italian)
Currently translated at 0.1% (1 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2024-04-12 11:47:34 +02:00
Anonymous
5b1eecfd7d Translated using Weblate (Norwegian Bokmål)
Currently translated at 1.6% (11 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2024-04-12 11:47:32 +02:00
Gooseman
ccce4f9edf Translated using Weblate (French)
Currently translated at 45.3% (297 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2024-04-12 11:47:30 +02:00
jokob-sk
5cb7553ed5 Rename work 🏗 2024-04-12 19:44:29 +10:00
github-actions[bot]
b003df323d [🤖Automation] Update README with sponsors information 2024-04-11 11:53:36 +00:00
Hosted Weblate
eb473cac21 Merge branch 'origin/main' into Weblate. 2024-04-11 12:01:48 +02:00
gallegonovato
6213fe84de Translated using Weblate (Spanish)
Currently translated at 100.0% (655 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-04-11 12:01:46 +02:00
github-actions[bot]
3e26cf67bb [🤖Automation] Update README with sponsors information 2024-04-10 11:53:49 +00:00
Anonymous
81fef80432 Translated using Weblate (Russian)
Currently translated at 98.7% (647 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-04-10 11:44:03 +02:00
Anonymous
67c18c16d0 Translated using Weblate (Spanish)
Currently translated at 99.8% (654 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-04-10 11:44:03 +02:00
Anonymous
5ca85137ac Translated using Weblate (German)
Currently translated at 87.7% (575 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-04-10 11:44:03 +02:00
github-actions[bot]
f32ebb2557 [🤖Automation] Update README with sponsors information 2024-04-09 11:53:36 +00:00
github-actions[bot]
052ce7362a [🤖Automation] Update README with sponsors information 2024-04-08 11:53:43 +00:00
jokob-sk
6c0de70c76 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2024-04-08 07:58:32 +10:00
jokob-sk
cacc52cd27 More rename work 2024-04-08 07:57:36 +10:00
github-actions[bot]
db765fe78d [🤖Automation] Update README with sponsors information 2024-04-07 11:53:50 +00:00
jokob-sk
8c023e4cb5 More rename work 2024-04-07 13:43:57 +10:00
jokob-sk
e9cc57a2fc Icons work 2024-04-07 13:32:44 +10:00
jokob-sk
4f04562b67 More rename work 2024-04-07 12:56:32 +10:00
jokob-sk
775a119f32 More rename work 2024-04-07 12:38:17 +10:00
jokob-sk
f06e084336 Intit NetAlertX dockerhub image 2024-04-07 10:27:40 +10:00
Anonymous
4329ff98ac Translated using Weblate (German)
Currently translated at 87.7% (575 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-04-07 02:00:49 +02:00
jokob-sk
4eae7e1023 Weblate 2024-04-07 09:55:37 +10:00
Anonymous
1bc2fe6cd2 Translated using Weblate (Italian)
Currently translated at 0.1% (1 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2024-04-07 01:48:51 +02:00
Safeguard
e0313f5970 Translated using Weblate (Russian)
Currently translated at 98.9% (648 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-04-07 01:48:50 +02:00
Anonymous
cdca7488fb Translated using Weblate (Norwegian Bokmål)
Currently translated at 1.6% (11 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2024-04-07 01:48:48 +02:00
Anonymous
f4068165d0 Translated using Weblate (German)
Currently translated at 88.5% (580 of 655 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-04-07 01:48:25 +02:00
jokob-sk
7653ddce63 PiAlert -> NetAlertX ✍ 2024-04-07 09:44:37 +10:00
Hosted Weblate
77eb472416 Merge branch 'origin/main' into Weblate. 2024-04-07 00:14:54 +02:00
Gooseman
1369017216 Translated using Weblate (French)
Currently translated at 45.3% (297 of 655 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2024-04-07 00:14:52 +02:00
gallegonovato
ad294cd612 Translated using Weblate (Spanish)
Currently translated at 100.0% (655 of 655 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-04-07 00:14:52 +02:00
Jokob-sk
3e0b980548 Settings tuning 2024-04-07 07:38:48 +10:00
Jokob-sk
116806b68b Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-04-07 07:04:31 +10:00
Jokob-sk
8155af8813 Docs 2024-04-07 07:04:27 +10:00
jokob-sk
1720df4036 Merge pull request #619 from wintergew/design-improvements
Design improvements - thanks a lot @wintergew 🙏
2024-04-07 07:00:20 +10:00
Emre Varci
13f5e68eba Replace fa-toggle's with solid and regular circles in the settings menu to improve design language 2024-04-06 21:03:08 +03:00
Emre Varci
7147f0691d Change card titles in the settings menu to white to increase accessibility 2024-04-06 21:02:18 +03:00
github-actions[bot]
70fcd90f8b [🤖Automation] Update README with sponsors information 2024-04-06 11:53:42 +00:00
github-actions[bot]
aec0002837 [🤖Automation] Update README with sponsors information 2024-04-05 11:54:23 +00:00
Jokob-sk
980e83e039 Icons work - docs 📚 #550 2024-04-05 20:09:05 +11:00
Jokob-sk
1f735e9ed5 Icons work #550 + Italian language 2024-04-05 19:20:43 +11:00
github-actions[bot]
f56d7c686d [🤖Automation] Update README with sponsors information 2024-04-04 11:54:03 +00:00
Jokob-sk
e51f2d06d0 UI auto-refresh #614 2024-04-04 07:41:25 +11:00
Jokob-sk
cbc9351961 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-04-03 23:02:04 +11:00
Jokob-sk
1367649554 UI auto-refresh #614 Schedule for undiscoverable devices to mark ONLINE work #617 2024-04-03 23:01:36 +11:00
github-actions[bot]
b4143607a1 [🤖Automation] Update README with sponsors information 2024-04-03 11:53:40 +00:00
github-actions[bot]
69450c5885 [🤖Automation] Update README with sponsors information 2024-04-02 11:53:39 +00:00
github-actions[bot]
cc19a6e3c0 [🤖Automation] Update README with sponsors information 2024-04-01 11:53:44 +00:00
Jokob-sk
af8c053ded UI hide Devices sections work #612 2024-04-01 12:26:28 +11:00
Jokob-sk
a672070ff0 UI show sections work + icons work 2024-04-01 11:48:17 +11:00
github-actions[bot]
f85466e1d6 [🤖Automation] Update README with sponsors information 2024-03-31 11:54:01 +00:00
github-actions[bot]
bb14627bbe [🤖Automation] Update README with sponsors information 2024-03-30 11:53:38 +00:00
github-actions[bot]
8ebe696a8d [🤖Automation] Update README with sponsors information 2024-03-29 11:53:44 +00:00
github-actions[bot]
2c5d95ba6d [🤖Automation] Update README with sponsors information 2024-03-28 11:53:53 +00:00
github-actions[bot]
ee6430e34e [🤖Automation] Update README with sponsors information 2024-03-27 11:53:55 +00:00
Hosted Weblate
f44ec2ce51 Merge branch 'origin/main' into Weblate. 2024-03-26 15:02:01 +01:00
Safeguard
962f355d1c Translated using Weblate (Russian)
Currently translated at 100.0% (648 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-03-26 15:01:57 +01:00
github-actions[bot]
f5b62a20dd [🤖Automation] Update README with sponsors information 2024-03-26 11:54:04 +00:00
github-actions[bot]
f09ac5bc86 [🤖Automation] Update README with sponsors information 2024-03-25 11:53:34 +00:00
jokob-sk
2beef711a4 Merge pull request #605 from ameer1234567890/patch-1
Removed duplicate manifest tag - thank you 🙏 @ameer1234567890
2024-03-24 20:21:24 +00:00
github-actions[bot]
990ace45d1 [🤖Automation] Update README with sponsors information 2024-03-24 11:54:00 +00:00
Ameer Dawood
28e0bc8403 Removed duplicate manifest tag 2024-03-24 16:52:14 +05:00
Jokob-sk
d7af5d6611 First load optimization 🔄 2024-03-24 18:43:06 +11:00
Jokob-sk
634e6a7499 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-24 10:38:18 +11:00
Jokob-sk
046022e2ea ngx prep ⏭ 2024-03-24 10:38:02 +11:00
github-actions[bot]
8d63c6b1ad [🤖Automation] Update README with sponsors information 2024-03-23 11:53:50 +00:00
Hosted Weblate
1d3eb50c01 Merge branch 'origin/main' into Weblate. 2024-03-23 11:02:04 +01:00
Safeguard
6588fc52cb Translated using Weblate (Russian)
Currently translated at 86.4% (560 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-03-23 11:02:01 +01:00
Jokob-sk
7f3938715c First-time load optimization 🔄 2024-03-23 13:04:08 +11:00
Jokob-sk
fc554dcbcb Cleanup 🧹 2024-03-23 12:31:53 +11:00
Jokob-sk
cb324890c8 DevDetails refactor 2024-03-23 09:56:53 +11:00
Jokob-sk
2336befcc1 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-22 23:06:08 +11:00
Jokob-sk
bb2accc194 DevDetails refactor 2024-03-22 23:05:52 +11:00
github-actions[bot]
67f3c6dea7 [🤖Automation] Update README with sponsors information 2024-03-22 11:53:51 +00:00
Jokob-sk
f9a999c4d0 tz work on #599 2024-03-22 12:38:11 +11:00
Jokob-sk
8d4d985fba path debug output #593, docs #598, Unassign network node #601 2024-03-22 11:37:17 +11:00
jokob-sk
63fc716359 Merge pull request #600 from vladaurosh/main
Improve chmod in setup.sh - thanks to @vladaurosh 🙏
2024-03-21 22:18:24 +00:00
vladaurosh
ff73b3e2c7 Update setup.sh
Reverting back one chmod command
2024-03-21 20:21:29 +00:00
github-actions[bot]
e7b70cc104 [🤖Automation] Update README with sponsors information 2024-03-21 11:53:40 +00:00
vladaurosh
7c084f31d1 Improve chmod in setup.sh 2024-03-21 02:03:57 +00:00
Jokob-sk
9b1cf13924 path debug 2024-03-21 10:03:46 +11:00
Jokob-sk
bb83b4b8bd removal of unnecessary env variables 2024-03-21 08:54:08 +11:00
github-actions[bot]
7d18dd546e [🤖Automation] Update README with sponsors information 2024-03-20 11:53:49 +00:00
Jokob-sk
5584512bcc pytz debug #596 2024-03-20 08:16:12 +11:00
Jokob-sk
de5e120042 roll-back of #593 2024-03-20 07:24:08 +11:00
Jokob-sk
d72812d280 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-19 23:06:27 +11:00
Jokob-sk
ea3871c69b font-awesome work 🩹 2024-03-19 23:06:08 +11:00
github-actions[bot]
220b14e261 [🤖Automation] Update README with sponsors information 2024-03-19 11:53:39 +00:00
Jokob-sk
27a3b9f6c9 WTZ bug #593 2024-03-19 17:09:54 +11:00
Hosted Weblate
b4001f54bb Merge branch 'origin/main' into Weblate. 2024-03-18 16:01:48 +01:00
gallegonovato
47d1740fdd Translated using Weblate (Spanish)
Currently translated at 100.0% (648 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-18 16:01:46 +01:00
github-actions[bot]
03d1e0e097 [🤖Automation] Update README with sponsors information 2024-03-18 11:53:42 +00:00
Jokob-sk
08ee4adddd Better first-load handling 🔄 2024-03-18 22:44:16 +11:00
Jokob-sk
1a221fabc9 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-18 22:02:41 +11:00
Jokob-sk
f412ca0636 Restart bug & docs 🩹 2024-03-18 22:02:29 +11:00
Anonymous
6beb2584e5 Translated using Weblate (Spanish)
Currently translated at 99.6% (646 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-17 15:18:08 +01:00
Anonymous
8419750bdd Translated using Weblate (German)
Currently translated at 89.5% (580 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-03-17 15:18:08 +01:00
Hosted Weblate
9364cea706 Merge branch 'origin/main' into Weblate. 2024-03-17 15:01:59 +01:00
gallegonovato
6ceff80ec5 Translated using Weblate (Spanish)
Currently translated at 100.0% (648 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-17 15:01:54 +01:00
github-actions[bot]
cc9e4c722a [🤖Automation] Update README with sponsors information 2024-03-17 11:53:52 +00:00
Jokob-sk
5e687e1bdb Netw root node fixes 🩹 2024-03-17 10:52:28 +11:00
Jokob-sk
d955e058e1 Multi edit ⚒ 2024-03-17 10:27:31 +11:00
Jokob-sk
0615611a49 UI tweaks 🩹 2024-03-17 09:41:16 +11:00
jokob-sk
59243813a8 Merge pull request #591 from Schlump/main
Add Pushover device support - thanks @Schlump 🙏
2024-03-17 08:23:32 +11:00
Schlump
195206c699 Update pushover.py 2024-03-16 15:34:22 +01:00
Schlump
2f170fb156 Update config.json 2024-03-16 15:34:10 +01:00
github-actions[bot]
e7764324dc [🤖Automation] Update README with sponsors information 2024-03-16 11:53:51 +00:00
Anonymous
958444984a Translated using Weblate (Spanish)
Currently translated at 98.9% (641 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-16 01:58:21 +01:00
Anonymous
594af4903e Translated using Weblate (German)
Currently translated at 89.5% (580 of 648 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-03-16 01:58:21 +01:00
Jokob-sk
dd4de7c5a3 UI tweaks 🩹 2024-03-16 11:54:37 +11:00
Jokob-sk
1fa49a7730 cache fixes 🩹 2024-03-16 11:24:24 +11:00
Jokob-sk
7c70d435e4 menu css fixes 🩹 2024-03-16 10:57:15 +11:00
Jokob-sk
2e159635c6 menuitem Integrations + docs 📚 2024-03-16 10:51:05 +11:00
Jokob-sk
23aa1e4e85 multi-edit floating, no-cache headers 🔘 2024-03-16 10:40:18 +11:00
Jokob-sk
a99dbaef78 sysinfo improvements 2024-03-16 09:42:21 +11:00
github-actions[bot]
06a1fa3512 [🤖Automation] Update README with sponsors information 2024-03-15 11:54:04 +00:00
github-actions[bot]
e2270b4439 [🤖Automation] Update README with sponsors information 2024-03-14 11:53:37 +00:00
github-actions[bot]
4c790c6ff2 [🤖Automation] Update README with sponsors information 2024-03-13 11:53:50 +00:00
github-actions[bot]
07432daa28 [🤖Automation] Update README with sponsors information 2024-03-12 11:53:38 +00:00
Jokob-sk
54901be437 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-11 23:15:21 +11:00
Jokob-sk
fb1e73d7d2 cleanup + drpdown fixes 2024-03-11 23:15:15 +11:00
github-actions[bot]
1401a24533 [🤖Automation] Update README with sponsors information 2024-03-11 11:53:39 +00:00
Jokob-sk
27ae11c1bc cleanup + log fixes 2024-03-11 07:57:49 +11:00
Jokob-sk
8817f8d0e9 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-03-10 23:07:04 +11:00
Jokob-sk
4f9e8c5ecd cleanup + fixes 2024-03-10 23:06:43 +11:00
github-actions[bot]
c201e98f5b [🤖Automation] Update README with sponsors information 2024-03-10 11:53:36 +00:00
Jokob-sk
7cd76178b1 cleanup + fixes 2024-03-10 22:48:49 +11:00
Jokob-sk
bcf4144364 cleanup + fixes 2024-03-10 22:41:33 +11:00
Jokob-sk
78352f77b7 cleanup + fixes 2024-03-10 22:21:43 +11:00
Jokob-sk
e38d2f9055 dynamic dropdown support in FE - core app feature 💠 2024-03-10 21:50:04 +11:00
Hosted Weblate
a66df76f74 Merge branch 'origin/main' into Weblate. 2024-03-10 00:01:57 +01:00
gallegonovato
a6d3c92d2a Translated using Weblate (Spanish)
Currently translated at 100.0% (643 of 643 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-10 00:01:55 +01:00
github-actions[bot]
9720a15e91 [🤖Automation] Update README with sponsors information 2024-03-09 11:53:39 +00:00
Jokob-sk
6a0033da75 lang updates 🌎 2024-03-09 08:27:39 +11:00
Jokob-sk
6fcdaf8843 Weblate 2024-03-09 08:22:35 +11:00
Anonymous
97fc553278 Translated using Weblate (Norwegian Bokmål)
Currently translated at 1.7% (11 of 646 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2024-03-08 22:19:18 +01:00
Anonymous
bb57080b06 Translated using Weblate (Russian)
Currently translated at 10.8% (70 of 646 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-03-08 22:17:41 +01:00
Anonymous
1310a4b751 Translated using Weblate (French)
Currently translated at 44.2% (286 of 646 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2024-03-08 22:17:41 +01:00
Anonymous
1c7e729036 Translated using Weblate (Spanish)
Currently translated at 99.5% (643 of 646 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-08 22:17:41 +01:00
Anonymous
d7af580488 Translated using Weblate (German)
Currently translated at 90.4% (584 of 646 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-03-08 22:17:40 +01:00
Jokob-sk
37e163e883 lang updates 🌎 2024-03-09 08:17:03 +11:00
Jokob-sk
785f7c03bf Menu updates🧭 2024-03-09 08:04:14 +11:00
github-actions[bot]
849c39d75d [🤖Automation] Update README with sponsors information 2024-03-08 11:54:03 +00:00
github-actions[bot]
c57e3e7557 [🤖Automation] Update README with sponsors information 2024-03-07 11:53:46 +00:00
github-actions[bot]
ddc747e192 [🤖Automation] Update README with sponsors information 2024-03-06 11:53:47 +00:00
Jokob-sk
92801d6ddc Menu updates🧭 2024-03-05 23:12:17 +11:00
github-actions[bot]
b6c464be6d [🤖Automation] Update README with sponsors information 2024-03-05 11:53:45 +00:00
Jokob-sk
be81668d6d Smooth scrolling 2024-03-05 16:17:52 +11:00
Jokob-sk
8e85abfda4 Paho MQTT Version slection support + JS/CSS fixes #580 🩹 2024-03-05 09:34:13 +11:00
github-actions[bot]
5559194617 [🤖Automation] Update README with sponsors information 2024-03-04 12:13:02 +00:00
github-actions[bot]
1cc5cd56f8 [🤖Automation] Update README with sponsors information 2024-03-03 11:53:52 +00:00
jokob-sk
9d4759898d Merge pull request #585 from vladaurosh/main
Adding lsblk package
2024-03-03 14:52:22 +11:00
root
178ff30938 Adding lsblk package 2024-03-03 03:46:27 +00:00
Jokob-sk
a44575926f caching fixes 🩹 2024-03-03 11:38:27 +11:00
Hosted Weblate
6a367c826e Merge branch 'origin/main' into Weblate. 2024-03-02 13:02:02 +01:00
gallegonovato
83336d3289 Translated using Weblate (Spanish)
Currently translated at 100.0% (644 of 644 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-03-02 13:02:00 +01:00
github-actions[bot]
12ba6fbdad [🤖Automation] Update README with sponsors information 2024-03-02 11:53:54 +00:00
Jokob-sk
17a4656c41 small fixes 🩹 #582 2024-03-02 14:20:12 +11:00
jokob-sk
7ef3fe5ac0 Merge pull request #583 from vladaurosh/main
Removing unneeded package, small tweaks
2024-03-02 13:59:15 +11:00
root
06c7ffa39e Fixing hardcoded path 2024-03-02 02:08:40 +00:00
root
9ac0163f20 removing unneeded package, small tweaks 2024-03-02 01:41:03 +00:00
Jokob-sk
0126e448cc alpine re-base cleanup 🧹 2024-03-02 10:29:45 +11:00
Jokob-sk
2362622cd0 alpine re-base cleanup 🧹 2024-03-02 10:06:32 +11:00
Jokob-sk
ca2df744df alpine re-base 2024-03-02 08:58:38 +11:00
jokob-sk
9420c41e7c Merge pull request #581 from vladaurosh/main
Adding support for alpine-based image - thanks to @vladaurosh 🙏
2024-03-02 08:30:14 +11:00
github-actions[bot]
a015466c7f [🤖Automation] Update README with sponsors information 2024-03-01 11:53:37 +00:00
root
89f2c28046 Adding support for alpine based image 2024-02-29 21:56:55 +00:00
github-actions[bot]
57d0680b6a [🤖Automation] Update README with sponsors information 2024-02-29 11:53:47 +00:00
Jokob-sk
ddd405f379 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-29 21:42:10 +11:00
Jokob-sk
3c38909b57 Multi edit CSS 2024-02-29 21:41:45 +11:00
github-actions[bot]
e830d1718e [🤖Automation] Update README with sponsors information 2024-02-28 11:53:39 +00:00
Jokob-sk
0ab78ffab7 merge 2024-02-28 21:12:10 +11:00
Jokob-sk
9685784452 Docs, Mass-delete 📚 2024-02-28 21:03:27 +11:00
Hosted Weblate
2a9085151f Merge branch 'origin/main' into Weblate. 2024-02-27 16:02:48 +01:00
Anonymous
c6fb35838a Translated using Weblate (German)
Currently translated at 91.2% (585 of 641 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2024-02-27 16:02:42 +01:00
github-actions[bot]
588ddf3cb3 [🤖Automation] Update README with sponsors information 2024-02-27 11:53:36 +00:00
Jokob-sk
84f96d72c8 Docs 📚 2024-02-27 08:07:11 +11:00
Jokob-sk
ed2ba9a435 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-27 08:04:04 +11:00
Jokob-sk
265d313719 mark TIMEOUT log entry as ERROR 2024-02-27 08:03:58 +11:00
Hosted Weblate
21ebc55335 Merge branch 'origin/main' into Weblate. 2024-02-26 16:02:00 +01:00
gallegonovato
a7bfc6f6f6 Translated using Weblate (Spanish)
Currently translated at 100.0% (641 of 641 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2024-02-26 16:01:58 +01:00
github-actions[bot]
369fc44183 [🤖Automation] Update README with sponsors information 2024-02-26 11:53:58 +00:00
github-actions[bot]
6a2a56e059 [🤖Automation] Update README with sponsors information 2024-02-25 11:53:44 +00:00
Jokob-sk
b0008ebd3f Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-25 09:45:34 +11:00
Jokob-sk
c624bfeae0 Docs 📚 2024-02-25 09:44:41 +11:00
github-actions[bot]
624d7499a5 [🤖Automation] Update README with sponsors information 2024-02-24 11:53:56 +00:00
Jokob-sk
4f5fbb1316 Multi-edit ✏ #571 2024-02-24 13:30:18 +11:00
github-actions[bot]
7d715493a6 [🤖Automation] Update README with sponsors information 2024-02-23 11:53:55 +00:00
github-actions[bot]
0c92bf8d0a [🤖Automation] Update README with sponsors information 2024-02-22 11:53:38 +00:00
github-actions[bot]
ea51b93263 [🤖Automation] Update README with sponsors information 2024-02-21 11:53:55 +00:00
github-actions[bot]
539556e01d [🤖Automation] Update README with sponsors information 2024-02-20 11:53:38 +00:00
Hosted Weblate
43e9fc324f Merge branch 'origin/main' into Weblate. 2024-02-20 10:19:54 +01:00
Safeguard
e6e4620e13 Translated using Weblate (Russian)
Currently translated at 11.1% (71 of 636 strings)

Translation: PiAlert/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2024-02-20 10:19:53 +01:00
github-actions[bot]
6963e0b507 [🤖Automation] Update README with sponsors information 2024-02-19 11:53:40 +00:00
Jokob-sk
460f8038f2 weblate 2024-02-19 21:37:45 +11:00
Jokob-sk
ee2e228e15 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-19 07:36:19 +11:00
Jokob-sk
15ab54f5d5 Hide labels in Online Presence #569 2024-02-19 07:36:03 +11:00
github-actions[bot]
2226b9ff39 [🤖Automation] Update README with sponsors information 2024-02-18 11:53:34 +00:00
Jokob-sk
d4b701653e PAHO MQTT API v2 2024-02-18 11:38:56 +11:00
Jokob-sk
34f5658516 ALWAYS_FRESH_INSTALL fix 2024-02-18 09:48:22 +11:00
Jokob-sk
ea7dfa832d docs 📚 2024-02-18 09:22:14 +11:00
Jokob-sk
9bbd549d93 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-18 08:28:13 +11:00
Jokob-sk
7424cf4645 docs 📚 + work on #569 2024-02-18 08:28:08 +11:00
github-actions[bot]
19f767a887 [🤖Automation] Update README with sponsors information 2024-02-17 11:53:36 +00:00
Jokob-sk
57d9024ed3 BACKUPS.md docs 📚 2024-02-17 10:08:00 +11:00
Jokob-sk
87dd1cdf2d ALWAYS_FRESH_INSTALL variable 2024-02-17 08:51:10 +11:00
Jokob-sk
fdf381d565 Merge branch 'main' of https://github.com/jokob-sk/Pi.Alert 2024-02-17 07:26:15 +11:00
Jokob-sk
20e29ecd15 Empty Devices error #568🩹 2024-02-17 07:25:42 +11:00
github-actions[bot]
a6ce702487 [🤖Automation] Update README with sponsors information 2024-02-16 11:53:42 +00:00
246 changed files with 7040 additions and 5135 deletions

View File

@@ -5,9 +5,15 @@
.gitignore
docker-compose.yml
Dockerfile
Dockerfile.debian
dockerfiles/LICENSE
dockerfiles/README.md
dockerfiles/README_ES.md
docs
LICENSE.txt
README.md
CONTRIBUTING
FUNDING.yml
config/.gitignore
db/.gitignore

2
.env
View File

@@ -7,8 +7,6 @@ LOGS_LOCATION=/path/to/docker_logs
#ENVIRONMENT VARIABLES
TZ=Europe/Paris
HOST_USER_ID=1000
HOST_USER_GID=1000
PORT=20211
#DEVELOPMENT VARIABLES

View File

@@ -1,5 +1,5 @@
name: Feature Request
description: 'Suggest an idea for PiAlert'
description: 'Suggest an idea for NetAlertX'
labels: ['Feature request']
body:
- type: checkboxes

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/Pi.Alert/tree/main/docs
- label: I have searched the existing open and closed issues and I checked the docs https://github.com/jokob-sk/NetAlertX/tree/main/docs
required: true
- type: textarea
attributes:
@@ -34,9 +34,9 @@ body:
required: false
- type: textarea
attributes:
label: pialert.conf
label: app.conf
description: |
Paste your `pialert.conf` (remove personal info)
Paste your `app.conf` (remove personal info)
render: python
validations:
required: false
@@ -58,13 +58,13 @@ body:
required: true
- type: textarea
attributes:
label: pialert.log
label: app.log
description: |
Logs with debug enabled (https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEBUG_TIPS.md) ⚠
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 /home/pi/pialert/front/log/pialert.log` in teh container if you have troubles getting to the log files.
You can use `tail -100 /app/front/log/app.log` in the container if you have troubles getting to the log files.
validations:
required: false
- type: checkboxes

View File

@@ -4,8 +4,8 @@ on:
workflow_dispatch: # manual option
schedule:
- cron: '15 22 * * 1' # every Monday 10.15pm UTC (~11.15am Tuesday NZT)
# schedule:
# - cron: '15 22 * * 1' # every Monday 10.15pm UTC (~11.15am Tuesday NZT)
jobs:
@@ -19,7 +19,7 @@ jobs:
- uses: actions/delete-package-versions@v4
with:
package-name: pi.alert
package-name: netalertx
package-type: container
min-versions-to-keep: 0
delete-only-untagged-versions: true

View File

@@ -20,7 +20,7 @@ jobs:
packages: write
if: >
contains(github.event.head_commit.message, 'PUSHPROD') != 'True' &&
github.repository == 'jokob-sk/Pi.Alert'
github.repository == 'jokob-sk/NetAlertX'
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -49,6 +49,7 @@ jobs:
# list of Docker images to use as base name for tags
images: |
jokobsk/pi.alert_dev
jokobsk/netalertx-dev
# generate Docker tags based on the following events/attributes
tags: |
type=raw,value=latest
@@ -87,5 +88,5 @@ jobs:
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/pi.alert:buildcache
# cache-to: type=registry,ref=ghcr.io/jokob-sk/pi.alert:buildcache,mode=max
# 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

@@ -13,7 +13,7 @@ on:
release:
types: [published]
tags:
- '*.*.*'
- '*.[1-9]+[0-9]?.[1-9]+*'
jobs:
docker:
runs-on: ubuntu-latest
@@ -49,6 +49,7 @@ jobs:
# list of Docker images to use as base name for tags
images: |
jokobsk/pi.alert
jokobsk/netalertx
# generate Docker tags based on the following events/attributes
tags: |
type=semver,pattern={{version}},value=${{ inputs.version }}
@@ -81,5 +82,5 @@ jobs:
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/pi.alert:buildcache
# cache-to: type=registry,ref=ghcr.io/jokob-sk/pi.alert:buildcache,mode=max
# cache-from: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache
# cache-to: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache,mode=max

2
.gitignore vendored
View File

@@ -2,8 +2,10 @@
.DS_Store
config/*
config/pialert.conf
config/app.conf
db/*
db/pialert.db
db/app.db
front/log/*
front/api/*
**/plugins/**/*.log

View File

@@ -6,8 +6,8 @@ The issue tracker is the preferred channel for bug reports, features requests an
Before submitting a new issue please spend a couple of minutes on research:
* Check [🛑 Common issues](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEBUG_TIPS.md#common-issues)
* Check [💡 Closed issues](https://github.com/jokob-sk/Pi.Alert/issues?q=is%3Aissue+is%3Aclosed) if a similar issue was solved in the past.
* Check [🛑 Common issues](https://github.com/jokob-sk/NetAlertX/blob/main/docs/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.
## Pull-requests (PRs)

View File

@@ -1,50 +1,54 @@
FROM debian:bookworm-slim
FROM alpine:3.19 as builder
# default UID and GID
ENV USER=pi USER_ID=1000 USER_GID=1000 PORT=20211
#TZ=Europe/London
ARG INSTALL_DIR=/app
# Todo, figure out why using a workdir instead of full paths don't work
# Todo, do we still need all these packages? I can already see sudo which isn't needed
ENV PYTHONUNBUFFERED 1
RUN apt-get update
RUN apt-get install sudo -y
RUN apk add --no-cache bash python3 \
&& python -m venv /opt/venv
# Enable venv
ENV PATH="/opt/venv/bin:$PATH"
# create pi user and group
# add root and www-data to pi group so they can r/w files and db
RUN groupadd --gid "${USER_GID}" "${USER}" && \
useradd \
--uid ${USER_ID} \
--gid ${USER_GID} \
--create-home \
--shell /bin/bash \
${USER} && \
usermod -a -G ${USER_GID} root && \
usermod -a -G ${USER_GID} www-data
COPY . ${INSTALL_DIR}/
COPY --chmod=775 --chown=${USER_ID}:${USER_GID} . /home/pi/pialert/
RUN pip install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet \
&& 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 'pialert-cli' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"
# second stage
FROM alpine:3.19 as runner
ARG INSTALL_DIR=/app
COPY --from=builder /opt/venv /opt/venv
# Enable venv
ENV PATH="/opt/venv/bin:$PATH"
# default port and listen address
ENV PORT=20211 LISTEN_ADDR=0.0.0.0
# needed for s6-overlay
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
# ❗ IMPORTANT - if you modify this file modify the /install/install_dependecies.sh file as well ❗
RUN apt-get install -y \
tini snmp ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo \
nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools \
python3 iproute2 nmap python3-pip zip systemctl usbutils traceroute
RUN apk update --no-cache \
&& apk add --no-cache bash zip lsblk gettext-envsubst sudo mtr tzdata s6-overlay \
&& apk add --no-cache curl arp-scan iproute2 iproute2-ss nmap nmap-scripts traceroute net-tools net-snmp-tools bind-tools awake ca-certificates \
&& apk add --no-cache sqlite php82 php82-fpm php82-cgi php82-curl php82-sqlite3 php82-session \
&& apk add --no-cache python3 nginx \
&& 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
# Alternate dependencies
RUN apt-get install nginx nginx-core mtr php-fpm php8.2-fpm php-cli php8.2 php8.2-sqlite3 -y
RUN phpenmod -v 8.2 sqlite3
COPY --from=builder --chown=nginx:www-data ${INSTALL_DIR}/ ${INSTALL_DIR}/
# Setup virtual python environment and use pip3 to install packages
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 requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet"
# Create a buildtimestamp.txt to later check if a new version was released
RUN date +%s > /home/pi/pialert/front/buildtimestamp.txt
CMD ["/home/pi/pialert/dockerfiles/start.sh"]
RUN ${INSTALL_DIR}/dockerfiles/pre-setup.sh
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=2 \
CMD curl -sf -o /dev/null ${LISTEN_ADDR}:${PORT}/api/app_state.json
ENTRYPOINT ["/init"]

51
Dockerfile.debian Executable file
View File

@@ -0,0 +1,51 @@
FROM debian:bookworm-slim
# default UID and GID
ENV USER=pi USER_ID=1000 USER_GID=1000 PORT=20211
#TZ=Europe/London
# Todo, figure out why using a workdir instead of full paths don't work
# Todo, do we still need all these packages? I can already see sudo which isn't needed
RUN apt-get update
RUN apt-get install sudo -y
ARG INSTALL_DIR=/app
# create pi user and group
# add root and www-data to pi group so they can r/w files and db
RUN groupadd --gid "${USER_GID}" "${USER}" && \
useradd \
--uid ${USER_ID} \
--gid ${USER_GID} \
--create-home \
--shell /bin/bash \
${USER} && \
usermod -a -G ${USER_GID} root && \
usermod -a -G ${USER_GID} www-data
COPY --chmod=775 --chown=${USER_ID}:${USER_GID} . ${INSTALL_DIR}/
# ❗ IMPORTANT - if you modify this file modify the /install/install_dependecies.debian.sh file as well ❗
RUN apt-get install -y \
tini snmp ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo \
nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools \
python3 iproute2 nmap python3-pip zip systemctl usbutils traceroute
# Alternate dependencies
RUN apt-get install nginx nginx-core mtr php-fpm php8.2-fpm php-cli php8.2 php8.2-sqlite3 -y
RUN phpenmod -v 8.2 sqlite3
# Setup virtual python environment and use pip3 to install packages
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 requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet"
# Create a buildtimestamp.txt to later check if a new version was released
RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt
CMD ["${INSTALL_DIR}/install/start.debian.sh"]

View File

@@ -1,14 +1,14 @@
# 💻🔍 Network security scanner & notification framework
Get visibility of what's going on on your WIFI/LAN network. Scan for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugins](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins#readme) with auto-generated UI and in-build notification system.
Get visibility of what's going on on your WIFI/LAN network. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
[![GitHub Committed](https://img.shields.io/github/last-commit/jokob-sk/Pi.Alert?color=40ba12&label=Committed&logo=GitHub&logoColor=fff)](https://github.com/jokob-sk/Pi.Alert)
[![Docker Size](https://img.shields.io/docker/image-size/jokobsk/pi.alert?label=Size&logo=Docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/pi.alert?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
![GitHub Release](https://img.shields.io/github/v/release/jokob-sk/Pi.Alert?color=0aa8d2&logoColor=fff&logo=GitHub)
[![GitHub Committed](https://img.shields.io/github/last-commit/jokob-sk/NetAlertX?color=40ba12&label=Committed&logo=GitHub&logoColor=fff)](https://github.com/jokob-sk/NetAlertX)
[![Docker Size](https://img.shields.io/docker/image-size/jokobsk/netalertx?label=Size&logo=Docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/netalertx)
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/netalertx?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/netalertx)
[![GitHub Release](https://img.shields.io/github/v/release/jokob-sk/NetAlertX?color=0aa8d2&logoColor=fff&logo=GitHub)](https://github.com/jokob-sk/NetAlertX/releases)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/jokob-sk?style=social)](https://github.com/sponsors/jokob-sk)
| 🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📑 [Docker guide](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) |🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/releases) | 📚 [All Docs](https://github.com/jokob-sk/Pi.Alert/tree/main/docs) |
| 🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/netalertx) | 📑 [Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) |🆕 [Release notes](https://github.com/jokob-sk/NetAlertX/releases) | 📚 [All Docs](https://github.com/jokob-sk/NetAlertX/tree/main/docs) |
|----------------------|----------------------| ----------------------| ----------------------|
@@ -25,19 +25,19 @@ Get visibility of what's going on on your WIFI/LAN network. Scan for devices, po
</details>
<details>
<summary>❓ Why use PiAlert?</summary>
<summary>❓ Why use Net <b>Alert</b><sup>x</sup>?</summary>
<hr>
Most of us don't know what's going on on our home network, but we want our family and data to be safe. _Command-line tools_ are great, but the output can be _hard to understand_ and action if you are not a network specialist.
PiAlert gives you peace of mind. _Visualize and immediately report 📬_ what is going on in your network - this is the first step to enhance your _network security 🔐_.
Net <b>Alert</b><sup>x</sup> gives you peace of mind. _Visualize and immediately report 📬_ what is going on in your network - this is the first step to enhance your _network security 🔐_.
PiAlert combines several network and other scanning tools 🔍 with notifications 📧 into one user-friendly package 📦.
Net <b>Alert</b><sup>x</sup> combines several network and other scanning tools 🔍 with notifications 📧 into one user-friendly package 📦.
Setup a _kill switch ☠_ for your network via a smart plug with the available [Home Assistant](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HOME_ASSISTANT.md) integration. Implement custom automations with the [CSV device Exports 📤](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins/csv_backup), [Webhooks](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md), or [API endpoints](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md) features.
Set up a _kill switch ☠_ for your network via a smart plug with the available [Home Assistant](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HOME_ASSISTANT.md) integration. Implement custom automations with the [CSV device Exports 📤](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup), [Webhooks](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md), or [API endpoints](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md) features.
Extend the app if you want to create your own scanner [Plugin](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins#readme) and handle the results and notifications in PiAlert.
Extend the app if you want to create your own scanner [Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) and handle the results and notifications in Net <b>Alert</b><sup>x</sup>.
Looking forward to your contributions if you decide to share your work with the community ❤.
@@ -47,10 +47,10 @@ Get visibility of what's going on on your WIFI/LAN network. Scan for devices, po
| Features | Details |
|-------------|-------------|
| 🔍 | 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/Pi.Alert/tree/main/front/plugins#readme) docs for more info on individual scans. |
| 🔍 | 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 more info on individual scans. |
|📧 | Send notifications to more than 80+ services, including Telegram via [Apprise](https://hub.docker.com/r/caronc/apprise), or use [Pushsafer](https://www.pushsafer.com/), [Pushover](https://www.pushover.net/), or [NTFY](https://ntfy.sh/). |
|🧩 | Feed your data and device changes into [Home Assistant](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HOME_ASSISTANT.md), read [API endpoints](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md), or use [Webhooks](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md) to setup custom automation flows. |
| | Build your own scanners with the [Plugin system](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins#readme) |
|🧩 | 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. |
| | Build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins#readme) |
## Installation & Documentation
@@ -58,9 +58,9 @@ Get visibility of what's going on on your WIFI/LAN network. Scan for devices, po
| Docs | Link |
|-------------|-------------|
| 📥🐳 | [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md)
| 📥💻 | [HW install (experimental 🧪)](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HW_INSTALL.md) |
| 📚 | [All Documentation](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/README.md) (App Usage and Configuration) |
| 📥🐳 | [Docker instructions](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
| 📥💻 | [HW install (experimental 🧪)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md) |
| 📚 | [All Documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/README.md) (App Usage and Configuration) |
> Other Alternatives
>
@@ -68,14 +68,22 @@ Get visibility of what's going on on your WIFI/LAN network. Scan for devices, po
> - Check instructions for [pucherot's original code](https://github.com/pucherot/Pi.Alert/) (unmaintained)
> - [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) - Lightweight network IP scanner with web GUI (Open source)
> - [Fing](https://www.fing.com/) - Network scanner app for your Internet security (Commercial, Phone App, Proprietary hardware)
> - [NetBox](https://netboxlabs.com/) - Network management software (Commercial)
## ❤ Support me for...
### ⭐ Sponsors
- I don't get burned out and the app survives longer🔥🤯
- Regular updates to keep your data and family safe 🔄
- Better and more functionality
- Quicker and better support with issues 🆘
- Less grumpy me 😄
[![GitHub Sponsors](https://img.shields.io/github/sponsors/jokob-sk?style=social)](https://github.com/sponsors/jokob-sk)
Thank you to all the wonderful people who are sponsoring this project.
> preventing my burnout😅 are:
<!-- SPONSORS-LIST DO NOT MODIFY BELOW -->
| All Sponsors |
|---|
| [Tony Hanratty](https://github.com/thanratty) |
<!-- SPONSORS-LIST DO NOT MODIFY ABOVE -->
| [![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) |
| --- | --- | --- |
@@ -88,25 +96,21 @@ Get visibility of what's going on on your WIFI/LAN network. Scan for devices, po
- Bitcoin: `1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM`
- Ethereum: `0x6e2749Cb42F4411bc98501406BdcD82244e3f9C7`
📧 Email me at [jokob@duck.com](mailto:jokob@duck.com?subject=PiAlert) if you want to get in touch or if I should add other sponsorship platforms.
📧 Email me at [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX) if you want to get in touch or if I should add other sponsorship platforms.
</details>
### 🙏Contributors
This project would be nothing without the amazing work of the community, with special thanks to:
### ⭐ Sponsors
> [pucherot/Pi.Alert](https://github.com/pucherot/Pi.Alert) (the original creator of PiAlert), [leiweibau](https://github.com/leiweibau/Pi.Alert): Dark mode (and much more), [Macleykun](https://github.com/Macleykun) (Help with Dockerfile clean-up) [Final-Hawk](https://github.com/Final-Hawk) (Help with NTFY, styling and other fixes), [TeroRERO](https://github.com/terorero) (Spanish translations), [Data-Monkey](https://github.com/Data-Monkey), (Split-up of the python.py file and more), [cvc90](https://github.com/cvc90) (Spanish translation and various UI work) to name a few...
[![GitHub Sponsors](https://img.shields.io/github/sponsors/jokob-sk?style=social)](https://github.com/sponsors/jokob-sk)
Here is everyone that helped and contributed to this project:
Thank you to all the wonderful people who are sponsoring this project (=preventing my burnout🔥🤯):
<!-- SPONSORS-LIST DO NOT MODIFY BELOW -->
| All Sponsors |
|---|
| [dtech77pl](https://github.com/dtech77pl) |
| [Tony Hanratty](https://github.com/thanratty) |
<!-- SPONSORS-LIST DO NOT MODIFY ABOVE -->
<a href="https://github.com/jokob-sk/netalertx/graphs/contributors">
<img src="https://contri-graphy.yourselfhosted.com/graph?repo=jokob-sk/netalertx&format=svg" />
</a>
## Everything else
<!--- --------------------------------------------------------------------- --->
@@ -124,13 +128,7 @@ Help out and suggest languages in the [online portal of Weblate](https://hosted.
### License
> GPL 3.0 | [Read more here](LICENSE.txt) | Source of the [animated GIF (Loading Animation)](https://commons.wikimedia.org/wiki/File:Loading_Animation.gif) | Source of the [selfhosted Fonts](https://github.com/adobe-fonts/source-sans)
### Special thanks
This code is a collaborative body of work, with special thanks to:
> [pucherot/Pi.Alert](https://github.com/pucherot/Pi.Alert) (the original creator of PiAlert), [leiweibau](https://github.com/leiweibau/Pi.Alert): Dark mode (and much more), [Macleykun](https://github.com/Macleykun) (Help with Dockerfile clean-up) [Final-Hawk](https://github.com/Final-Hawk) (Help with NTFY, styling and other fixes), [TeroRERO](https://github.com/terorero) (Spanish translations), [Data-Monkey](https://github.com/Data-Monkey), (Split-up of the python.py file and more), [cvc90](https://github.com/cvc90) (Spanish translation and various UI work) to name a few...
>
> Please see the [Git contributors](https://github.com/jokob-sk/Pi.Alert/graphs/contributors) for a full list of people and their contributions to the project
<!--- --------------------------------------------------------------------- --->
[main]: ./docs/img/devices_split.png "Main screen"

View File

@@ -3,10 +3,12 @@
# Generated: 2022-12-30_22-19-40 #
# #
# Config file for the LAN intruder detection app: #
# https://github.com/jokob-sk/Pi.Alert #
# https://github.com/jokob-sk/NetAlertX #
# #
#-----------------AUTOGENERATED FILE-----------------#
# 🔺 Use the Settings UI - only edit when necessary 🔺
# General
#---------------------------
@@ -23,16 +25,16 @@ PIALERT_WEB_PROTECTION=False
PIALERT_WEB_PASSWORD='8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'
DAYS_TO_KEEP_EVENTS=90
# Used for generating links in emails. Make sure not to add a trailing slash!
REPORT_DASHBOARD_URL='http://pi.alert'
REPORT_DASHBOARD_URL='http://netalertx'
# Email
#---------------------------
REPORT_MAIL=False
SMTP_RUN='disabled' # use 'on_notification' to enable
SMTP_SERVER='smtp.gmail.com'
SMTP_PORT=587
REPORT_TO='user@gmail.com'
REPORT_FROM='Pi.Alert <user@gmail.com>'
SMTP_REPORT_TO='user@gmail.com'
SMTP_REPORT_FROM='NetAlertX <user@gmail.com>'
SMTP_SKIP_LOGIN=False
SMTP_USER='user@gmail.com'
SMTP_PASS='password'
@@ -41,10 +43,10 @@ SMTP_SKIP_TLS=False
# Webhooks
#---------------------------
REPORT_WEBHOOK=False
WEBHOOK_RUN='disabled' # use 'on_notification' to enable
WEBHOOK_URL='http://n8n.local:5555/webhook-test/aaaaaaaa-aaaa-aaaa-aaaaa-aaaaaaaaaaaa'
WEBHOOK_PAYLOAD='json' # webhook payload data format for the "body > attachements > text" attribute
# in https://github.com/jokob-sk/Pi.Alert/blob/main/docs/webhook_json_sample.json
# in https://github.com/jokob-sk/NetAlertX/blob/main/docs/webhook_json_sample.json
# supported values: 'json', 'html' or 'text'
# e.g.: for discord use 'html'
WEBHOOK_REQUEST_METHOD='GET'
@@ -52,14 +54,14 @@ WEBHOOK_REQUEST_METHOD='GET'
# Apprise
#---------------------------
REPORT_APPRISE=False
APPRISE_RUN='disabled' # use 'on_notification' to enable
APPRISE_HOST='http://localhost:8000/notify'
APPRISE_URL='mailto://smtp-relay.sendinblue.com:587?from=user@gmail.com&name=apprise&user=user@gmail.com&pass=password&to=user@gmail.com'
# NTFY
#---------------------------
REPORT_NTFY=False
NTFY_RUN='disabled' # use 'on_notification' to enable
NTFY_HOST='https://ntfy.sh'
NTFY_TOPIC='replace_my_secure_topicname_91h889f28'
NTFY_USER='user'
@@ -68,13 +70,13 @@ NTFY_PASSWORD='passw0rd'
# PUSHSAFER
#---------------------------
REPORT_PUSHSAFER=False
PUSHSAFER_RUN='disabled' # use 'on_notification' to enable
PUSHSAFER_TOKEN='ApiKey'
# MQTT
#---------------------------
REPORT_MQTT=False
MQTT_RUN='disabled' # use 'on_notification' to enable
MQTT_BROKER='192.168.1.2'
MQTT_PORT=1883
MQTT_USER='mqtt'
@@ -83,15 +85,6 @@ MQTT_QOS=0
MQTT_DELAY_SEC=2
# DynDNS
#---------------------------
DDNS_ACTIVE=False
DDNS_DOMAIN='your_domain.freeddns.org'
DDNS_USER='dynu_user'
DDNS_PASSWORD='A0000000B0000000C0000000D0000000'
DDNS_UPDATE_URL='https://api.dynu.com/nic/update?'
#-------------------IMPORTANT INFO-------------------#
# This file is ingested by a python script, so if #
# modified it needs to use python syntax #

View File

@@ -1,7 +1,10 @@
#!/bin/bash
SCRIPT=$(readlink -f $0)
SCRIPTPATH=`dirname $SCRIPT`
PIA_CONF_FILE=${SCRIPTPATH}'/../config/pialert.conf'
SCRIPTPATH=$(dirname $SCRIPT)
CONFFILENAME="app.conf"
SETTING_NAME_TOGGLE="PIALERT_WEB_PROTECTION"
SETTING_NAME_PWD="PIALERT_WEB_PASSWORD"
PIA_CONF_FILE=${SCRIPTPATH}'/../config/${CONFFILENAME}'
case $1 in
@@ -11,94 +14,89 @@ case $1 in
echo ""
echo "The is a list of supported commands:"
echo ""
echo " set_login - Sets the parameter PIALERT_WEB_PROTECTION in the config file to TRUE"
echo " set_login - Sets the parameter $SETTING_NAME_TOGGLE in the config file to TRUE"
echo " - If the parameter is not present, it will be created. Additionally the"
echo " default password '123456' is set."
echo ""
echo " unset_login - Sets the parameter PIALERT_WEB_PROTECTION in the config file to FALSE"
echo " unset_login - Sets the parameter $SETTING_NAME_TOGGLE in the config file to FALSE"
echo " - If the parameter is not present, it will be created. Additionally the"
echo " default password '123456' is set."
echo ""
echo " set_password <password> - Sets the new password as a hashed value."
echo " - If the PIALERT_WEB_PROTECTION parameter does not exist yet, it will be"
echo " - If the $SETTING_NAME_TOGGLE parameter does not exist yet, it will be"
echo " created and set to 'True' (login enabled)"
echo ""
echo " set_autopassword - Sets a new random password as a hashed value and show it plaintext in"
echo " the console."
echo " - If the PIALERT_WEB_PROTECTION parameter does not exist yet, it will be"
echo " - If the $SETTING_NAME_TOGGLE parameter does not exist yet, it will be"
echo " created and set to 'True' (login enabled)"
echo ""
echo " disable_scan - Stops all active scans"
echo " - Prevents new scans from starting"
echo ""
echo " enable_scan - Stops all active scans"
echo " - Prevents new scans from starting"
echo ""
echo ""
;;
set_login)
## Check if PIALERT_WEB_PROTECTION exists
CHECK_PROT=$(grep "PIALERT_WEB_PROTECTION" $PIA_CONF_FILE | wc -l)
## Check if $SETTING_NAME_TOGGLE exists
CHECK_PROT=$(grep "$SETTING_NAME_TOGGLE" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PROT -eq 0 ]
then
## Create PIALERT_WEB_PROTECTION and enable it
sed -i "/^VENDORS_DB.*/a PIALERT_WEB_PROTECTION = True" $PIA_CONF_FILE
sed -i "/^PIALERT_WEB_PROTECTION.*/a PIALERT_WEB_PASSWORD = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'" $PIA_CONF_FILE
## Create $SETTING_NAME_TOGGLE and enable it
sed -i "/^VENDORS_DB.*/a $SETTING_NAME_TOGGLE = True" $PIA_CONF_FILE
sed -i "/^$SETTING_NAME_TOGGLE.*/a $SETTING_NAME_PWD = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'" $PIA_CONF_FILE
else
## Switch PIALERT_WEB_PROTECTION to enable
sed -i "/PIALERT_WEB_PROTECTION/c\PIALERT_WEB_PROTECTION = True" $PIA_CONF_FILE
## Switch $SETTING_NAME_TOGGLE to enable
sed -i "/$SETTING_NAME_TOGGLE/c\$SETTING_NAME_TOGGLE = True" $PIA_CONF_FILE
fi
echo "Login is now enabled"
;;
unset_login)
## Check if PIALERT_WEB_PROTECTION exists
CHECK_PROT=$(grep "PIALERT_WEB_PROTECTION" $PIA_CONF_FILE | wc -l)
## Check if $SETTING_NAME_TOGGLE exists
CHECK_PROT=$(grep "$SETTING_NAME_TOGGLE" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PROT -eq 0 ]
then
## Create PIALERT_WEB_PROTECTION and disable it
sed -i "/^VENDORS_DB.*/a PIALERT_WEB_PROTECTION = False" $PIA_CONF_FILE
sed -i "/^PIALERT_WEB_PROTECTION.*/a PIALERT_WEB_PASSWORD = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'" $PIA_CONF_FILE
## Create $SETTING_NAME_TOGGLE and disable it
sed -i "/^VENDORS_DB.*/a $SETTING_NAME_TOGGLE = False" $PIA_CONF_FILE
sed -i "/^$SETTING_NAME_TOGGLE.*/a $SETTING_NAME_PWD = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'" $PIA_CONF_FILE
else
## Switch PIALERT_WEB_PROTECTION to disable
sed -i "/PIALERT_WEB_PROTECTION/c\PIALERT_WEB_PROTECTION = False" $PIA_CONF_FILE
## Switch $SETTING_NAME_TOGGLE to disable
sed -i "/$SETTING_NAME_TOGGLE/c\$SETTING_NAME_TOGGLE = False" $PIA_CONF_FILE
fi
echo "Login is now disabled"
;;
set_password)
PIA_PASS=$2
## Check if PIALERT_WEB_PROTECTION exists
CHECK_PROT=$(grep "PIALERT_WEB_PROTECTION" $PIA_CONF_FILE | wc -l)
## Check if $SETTING_NAME_TOGGLE exists
CHECK_PROT=$(grep "$SETTING_NAME_TOGGLE" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PROT -eq 0 ]
then
## Create PIALERT_WEB_PROTECTION and enable it
sed -i "/^VENDORS_DB.*/a PIALERT_WEB_PROTECTION = True" $PIA_CONF_FILE
## Create $SETTING_NAME_TOGGLE and enable it
sed -i "/^VENDORS_DB.*/a $SETTING_NAME_TOGGLE = True" $PIA_CONF_FILE
fi
## Prepare Hash
PIA_PASS_HASH=$(echo -n $PIA_PASS | sha256sum | awk '{print $1}')
echo " The hashed password is:"
echo " $PIA_PASS_HASH"
## Check if the password parameter is set
CHECK_PWD=$(grep "PIALERT_WEB_PASSWORD" $PIA_CONF_FILE | wc -l)
CHECK_PWD=$(grep "$SETTING_NAME_PWD" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PWD -eq 0 ]
then
sed -i "/^PIALERT_WEB_PROTECTION.*/a PIALERT_WEB_PASSWORD = '$PIA_PASS_HASH'" $PIA_CONF_FILE
sed -i "/^$SETTING_NAME_TOGGLE.*/a $SETTING_NAME_PWD = '$PIA_PASS_HASH'" $PIA_CONF_FILE
else
sed -i "/PIALERT_WEB_PASSWORD/c\PIALERT_WEB_PASSWORD = '$PIA_PASS_HASH'" $PIA_CONF_FILE
sed -i "/$SETTING_NAME_PWD/c\$SETTING_NAME_PWD = '$PIA_PASS_HASH'" $PIA_CONF_FILE
fi
echo ""
echo "The new password is set"
;;
set_autopassword)
## Check if PIALERT_WEB_PROTECTION exists
CHECK_PROT=$(grep "PIALERT_WEB_PROTECTION" $PIA_CONF_FILE | wc -l)
## Check if $SETTING_NAME_TOGGLE exists
CHECK_PROT=$(grep "$SETTING_NAME_TOGGLE" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PROT -eq 0 ]
then
## Create PIALERT_WEB_PROTECTION and enable it
sed -i "/^VENDORS_DB.*/a PIALERT_WEB_PROTECTION = True" $PIA_CONF_FILE
## Create $SETTING_NAME_TOGGLE and enable it
sed -i "/^VENDORS_DB.*/a $SETTING_NAME_TOGGLE = True" $PIA_CONF_FILE
fi
## Create autopassword
PIA_AUTOPASS=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
@@ -108,34 +106,20 @@ case $1 in
echo " The hashed password is:"
echo " $PIA_AUTOPASS_HASH"
## Check if the password parameter is set
CHECK_PWD=$(grep "PIALERT_WEB_PASSWORD" $PIA_CONF_FILE | wc -l)
CHECK_PWD=$(grep "$SETTING_NAME_PWD" $PIA_CONF_FILE | wc -l)
if [ $CHECK_PWD -eq 0 ]
then
## Create password parameter
sed -i "/^PIALERT_WEB_PROTECTION.*/a PIALERT_WEB_PASSWORD = '$PIA_AUTOPASS_HASH'" $PIA_CONF_FILE
sed -i "/^$SETTING_NAME_TOGGLE.*/a $SETTING_NAME_PWD = '$PIA_AUTOPASS_HASH'" $PIA_CONF_FILE
else
## Overwrite password parameter
sed -i "/PIALERT_WEB_PASSWORD/c\PIALERT_WEB_PASSWORD = '$PIA_AUTOPASS_HASH'" $PIA_CONF_FILE
sed -i "/$SETTING_NAME_PWD/c\$SETTING_NAME_PWD = '$PIA_AUTOPASS_HASH'" $PIA_CONF_FILE
fi
echo ""
echo "The new password is set"
;;
disable_scan)
## stop active scans
sudo killall arp-scan
touch ${SCRIPTPATH}/../db/setting_stoparpscan
echo "The arp-scan is disabled"
;;
enable_scan)
## stop active scans
rm ${SCRIPTPATH}/../db/setting_stoparpscan
echo "The arp-scan is enabled"
;;
*)
echo "pialert-cli v0.1 (https://github.com/leiweibau/Pi.Alert)"
echo "Use \"pialert-cli help\" for a list of supported commands."
esac

View File

@@ -1,70 +0,0 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# report_template.html - Back module. Template to email reporting in HTML format #
#---------------------------------------------------------------------------------#
# 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 #
#---------------------------------------------------------------------------------#
-->
<html>
<head>
</head>
<body>
<font face=sans-serif>
<table align=center width=100% cellpadding=0 cellspacing=0 style="border-radius: 5px;">
<tr>
<td bgcolor=#3c8dbc align=center style="padding: 20px 10px 10px 10px; font-size: 30px; font-weight: bold; color:#ffffff; border-top-right-radius: 5px; border-top-left-radius: 5px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
Pi.Alert Report
</td>
</tr>
<tr>
<td>
<table width=100% border=0 bgcolor=#4b99d3 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 15px; text-align:center; color:#ffffff"> <tr>
<td width=100% bgcolor="#3c8dbc"> Report Date: <b><REPORT_DATE></b> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td height=200 valign=top style="padding: 10px">
<NEW_DEVICES_TABLE>
<DOWN_DEVICES_TABLE>
<EVENTS_TABLE>
<PLUGINS_TABLE>
</td>
</tr>
<tr>
<td>
<table width=100% bgcolor=#3c8dbc cellpadding=5px cellspacing=0 style="font-size: 13px; font-weight: bold; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px;">
<tr>
<td width=50% style="text-align:center;color: white;" bgcolor="#3c8dbc">
<a href="https://github.com/jokob-sk/Pi.Alert" target="_blank" style="color: white">Pi.Alert</a>
<a href=".." target="_blank" style="color: white"> (<SERVER_NAME>)</a>
<br><span style="display:inline-block;color: white; transform: rotate(180deg)">&copy;</span>2020 Puche (2022+
<a style="color: white" href="mailto:jokob@duck.com?subject=PiAlert">jokob-sk</a>) | <b>Built on: <BUILD_PIALERT> </b> | <b> Version: <VERSION_PIALERT> </b> |
<a href="https://github.com/jokob-sk/Pi.Alert/tree/main/docs" target="_blank" style="color: white">
<span>Docs <i class="fa fa-circle-question"></i>
</a><span>
</td>
</tr>
</table>
</td>
</tr>
</table>
</font>
</body>
</html>

View File

@@ -1,74 +0,0 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# report_template_new_version - Back module. Template to email reporting in text #
#---------------------------------------------------------------------------------#
# 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 #
#---------------------------------------------------------------------------------#
-->
<html>
<head>
</head>
<body>
<font face=sans-serif>
<table align=center width=100% cellpadding=0 cellspacing=0 style="border-radius: 5px;">
<tr>
<td bgcolor=#3c8dbc align=center style="padding: 20px 10px 10px 10px; font-size: 30px; font-weight: bold; color:#ffffff; border-top-right-radius: 5px; border-top-left-radius: 5px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
Pi.Alert Report
</td>
</tr>
<tr>
<td bgcolor=#2656f1 width=100% align=center style="padding: 20px 10px 10px 10px; font-size: 20px; font-weight: bold; color:#ffffff; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
<a style="color:#ffffff;cursor:pointer;" href="https://github.com/jokob-sk/Pi.Alert/releases">🆕 New version available 🆕</a>
</td>
</tr>
<tr>
<td>
<table width=100% border=0 bgcolor=#4b99d3 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 15px; text-align:center; color:#ffffff"> <tr>
<td width=100% bgcolor="#3c8dbc"> Report Date: <b><REPORT_DATE></b> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td height=200 valign=top style="padding: 10px">
<NEW_DEVICES_TABLE>
<DOWN_DEVICES_TABLE>
<EVENTS_TABLE>
<PLUGINS_TABLE>
</td>
</tr>
<tr>
<td>
<table width=100% bgcolor=#3c8dbc cellpadding=5px cellspacing=0 style="font-size: 13px; font-weight: bold; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px;">
<tr>
<td width=50% style="text-align:center;color: white;" bgcolor="#3c8dbc">
<a href="https://github.com/jokob-sk/Pi.Alert" target="_blank" style="color: white">Pi.Alert</a>
<a href=".." target="_blank" style="color: white"> (<SERVER_NAME>)</a>
<br><span style="display:inline-block;color: white; transform: rotate(180deg)">&copy;</span>2020 Puche (2022+
<a style="color: white" href="mailto:jokob@duck.com?subject=PiAlert">jokob-sk</a>) | <b>Built on: <BUILD_PIALERT> </b> | <b> Version: <VERSION_PIALERT> </b> |
<a href="https://github.com/jokob-sk/Pi.Alert/tree/main/docs" target="_blank" style="color: white">
<span>Docs <i class="fa fa-circle-question"></i>
</a><span>
</td>
</tr>
</table>
</td>
</tr>
</table>
</font>
</body>
</html>

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Pi.Alert
# NetAlertX
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# update_vendors.sh - Back module. IEEE Vendors db update

View File

@@ -1,65 +1,69 @@
version: "3"
services:
pialert:
netalertx:
privileged: true
build:
dockerfile: Dockerfile
context: .
cache_from:
- type=registry,ref=docker.io/jokob-sk/pi.alert:buildcache
container_name: pialert
- type=registry,ref=docker.io/jokob-sk/netalertx:buildcache
container_name: netalertx
network_mode: host
# restart: unless-stopped
volumes:
- ${APP_DATA_LOCATION}/pialert_dev/config:/home/pi/pialert/config
# - ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
- ${APP_DATA_LOCATION}/pialert_dev/db:/home/pi/pialert/db
# - ${APP_DATA_LOCATION}/pialert/db:/home/pi/pialert/db
# - ${APP_DATA_LOCATION}/netalertx_dev/config:/app/config
# - ${APP_DATA_LOCATION}/netalertx/config:/app/config
- ${APP_DATA_LOCATION}/netalertx/config:/home/pi/pialert/config
# - ${APP_DATA_LOCATION}/netalertx_dev/db:/app/db
# - ${APP_DATA_LOCATION}/netalertx/db:/app/db
- ${APP_DATA_LOCATION}/netalertx/db:/home/pi/pialert/db
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
# - ${LOGS_LOCATION}:/app/front/log
# ---------------------------------------------------------------------------
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases
- ${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}/pialert:/home/pi/pialert/pialert
- ${DEV_LOCATION}/dockerfiles:/home/pi/pialert/dockerfiles
- ${APP_DATA_LOCATION}/pialert/php.ini:/etc/php/8.2/fpm/php.ini
- ${DEV_LOCATION}/install:/home/pi/pialert/install
- ${DEV_LOCATION}/front/css:/home/pi/pialert/front/css
- ${DEV_LOCATION}/back/update_vendors.sh:/home/pi/pialert/back/update_vendors.sh
- ${DEV_LOCATION}/front/lib/AdminLTE:/home/pi/pialert/front/lib/AdminLTE
- ${DEV_LOCATION}/front/js:/home/pi/pialert/front/js
- ${DEV_LOCATION}/dockerfiles/start.sh:/home/pi/pialert/dockerfiles/start.sh
- ${DEV_LOCATION}/dockerfiles/user-mapping.sh:/home/pi/pialert/dockerfiles/user-mapping.sh
- ${DEV_LOCATION}/install/install.sh:/home/pi/pialert/install/install.sh
- ${DEV_LOCATION}/install/install_dependencies.sh:/home/pi/pialert/install/install_dependencies.sh
- ${DEV_LOCATION}/front/api:/home/pi/pialert/front/api
- ${DEV_LOCATION}/front/php:/home/pi/pialert/front/php
- ${DEV_LOCATION}/front/deviceDetails.php:/home/pi/pialert/front/deviceDetails.php
- ${DEV_LOCATION}/front/deviceDetailsTools.php:/home/pi/pialert/front/deviceDetailsTools.php
- ${DEV_LOCATION}/front/devices.php:/home/pi/pialert/front/devices.php
- ${DEV_LOCATION}/front/events.php:/home/pi/pialert/front/events.php
- ${DEV_LOCATION}/front/plugins.php:/home/pi/pialert/front/plugins.php
- ${DEV_LOCATION}/front/pluginsCore.php:/home/pi/pialert/front/pluginsCore.php
- ${DEV_LOCATION}/front/help_faq.php:/home/pi/pialert/front/help_faq.php
- ${DEV_LOCATION}/front/index.php:/home/pi/pialert/front/index.php
- ${DEV_LOCATION}/front/maintenance.php:/home/pi/pialert/front/maintenance.php
- ${DEV_LOCATION}/front/network.php:/home/pi/pialert/front/network.php
- ${DEV_LOCATION}/front/presence.php:/home/pi/pialert/front/presence.php
- ${DEV_LOCATION}/front/settings.php:/home/pi/pialert/front/settings.php
- ${DEV_LOCATION}/front/systeminfo.php:/home/pi/pialert/front/systeminfo.php
- ${DEV_LOCATION}/front/report.php:/home/pi/pialert/front/report.php
- ${DEV_LOCATION}/front/workflows.php:/home/pi/pialert/front/workflows.php
- ${DEV_LOCATION}/front/appEventsCore.php:/home/pi/pialert/front/appEventsCore.php
- ${DEV_LOCATION}/front/donations.php:/home/pi/pialert/front/donations.php
- ${DEV_LOCATION}/front/plugins:/home/pi/pialert/front/plugins
- ${DEV_LOCATION}/server:/app/server
- ${DEV_LOCATION}/dockerfiles:/app/dockerfiles
- ${APP_DATA_LOCATION}/netalertx/php.ini:/etc/php/8.2/fpm/php.ini
- ${DEV_LOCATION}/install:/app/install
- ${DEV_LOCATION}/front/css:/app/front/css
- ${DEV_LOCATION}/front/img:/app/front/img
- ${DEV_LOCATION}/back/update_vendors.sh:/app/back/update_vendors.sh
- ${DEV_LOCATION}/front/lib/AdminLTE:/app/front/lib/AdminLTE
- ${DEV_LOCATION}/front/js:/app/front/js
- ${DEV_LOCATION}/install/start.debian.sh:/app/install/start.debian.sh
- ${DEV_LOCATION}/install/user-mapping.debian.sh:/app/install/user-mapping.debian.sh
- ${DEV_LOCATION}/install/install.debian.sh:/app/install/install.debian.sh
- ${DEV_LOCATION}/install/install_dependencies.debian.sh:/app/install/install_dependencies.debian.sh
- ${DEV_LOCATION}/front/api:/app/front/api
- ${DEV_LOCATION}/front/php:/app/front/php
- ${DEV_LOCATION}/front/deviceDetails.php:/app/front/deviceDetails.php
- ${DEV_LOCATION}/front/deviceDetailsTools.php:/app/front/deviceDetailsTools.php
- ${DEV_LOCATION}/front/devices.php:/app/front/devices.php
- ${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
- ${DEV_LOCATION}/front/presence.php:/app/front/presence.php
- ${DEV_LOCATION}/front/settings.php:/app/front/settings.php
- ${DEV_LOCATION}/front/systeminfo.php:/app/front/systeminfo.php
- ${DEV_LOCATION}/front/report.php:/app/front/report.php
- ${DEV_LOCATION}/front/workflows.php:/app/front/workflows.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
# ---------------------------------------------------------------------------
environment:
- TZ=${TZ}
- PORT=${PORT}
- HOST_USER_ID=${HOST_USER_ID}
- HOST_USER_GID=${HOST_USER_GID}
# ❗ DANGER ZONE BELOW - Setting ALWAYS_FRESH_INSTALL=true will delete the content of the /db & /config folders
- ALWAYS_FRESH_INSTALL=${ALWAYS_FRESH_INSTALL}

View File

@@ -1,23 +1,23 @@
[![GitHub Committed](https://img.shields.io/github/last-commit/jokob-sk/Pi.Alert?color=40ba12&label=Committed&logo=GitHub&logoColor=fff)](https://github.com/jokob-sk/Pi.Alert)
[![Docker Size](https://img.shields.io/docker/image-size/jokobsk/pi.alert?label=Size&logo=Docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/pi.alert?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
![GitHub Release](https://img.shields.io/github/v/release/jokob-sk/Pi.Alert?color=0aa8d2&logoColor=fff&logo=GitHub)
[![GitHub Committed](https://img.shields.io/github/last-commit/jokob-sk/NetAlertX?color=40ba12&label=Committed&logo=GitHub&logoColor=fff)](https://github.com/jokob-sk/NetAlertX)
[![Docker Size](https://img.shields.io/docker/image-size/jokobsk/netalertx?label=Size&logo=Docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/netalertx)
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/netalertx?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/netalertx)
![GitHub Release](https://img.shields.io/github/v/release/jokob-sk/NetAlertX?color=0aa8d2&logoColor=fff&logo=GitHub)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/jokob-sk?style=social)](https://github.com/sponsors/jokob-sk)
# PiAlert 💻🔍 Network security scanner & notification framework
# NetAlertX 💻🔍 Network security scanner & notification framework
| 🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📑 [Docker guide](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) |🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/releases) | 📚 [All Docs](https://github.com/jokob-sk/Pi.Alert/tree/main/docs) |
| 🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/netalertx) | 📑 [Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) |🆕 [Release notes](https://github.com/jokob-sk/NetAlertX/releases) | 📚 [All Docs](https://github.com/jokob-sk/NetAlertX/tree/main/docs) |
|----------------------|----------------------| ----------------------| ----------------------|
<a href="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" width="300px" />
<a href="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/devices_split.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/devices_split.png" width="300px" />
</a>
<a href="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/network.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/network.png" width="300px" />
<a href="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/network.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/network.png" width="300px" />
</a>
> [!NOTE]
> There is also an experimental 🧪 [bare-metal install](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HW_INSTALL.md) method available.
> There is also an experimental 🧪 [bare-metal install](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md) method available.
## 📕 Basic Usage
@@ -25,11 +25,11 @@
```yaml
docker run -d --rm --network=host \
-v local/path/pialert/config:/home/pi/pialert/config \
-v local/path/pialert/db:/home/pi/pialert/db \
-v local/path/config:/app/config \
-v local/path/db:/app/db \
-e TZ=Europe/Berlin \
-e PORT=20211 \
jokobsk/pi.alert:latest
jokobsk/netalertx:latest
```
- The initial scan can take up to 15min (with 50 devices and MQTT). Subsequent ones 3 and 5 minutes so wait that long for all of the scans to run.
@@ -40,28 +40,31 @@ docker run -d --rm --network=host \
| `PORT` |Port of the web interface | `20211` |
| `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` |
|`HOST_USER_GID` |User ID (UID) to map the user in the container to a server user with sufficient read&write permissions on the mapped files | `1000` |
|`HOST_USER_ID` |User Group ID (GID) to map the user group in the container to a server user group with sufficient read&write permissions on the mapped files | `1000` |
|`ALWAYS_FRESH_INSTALL` | Setting `ALWAYS_FRESH_INSTALL=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`/`-dev` image. | `N/A` |
### Docker paths
> [!NOTE]
> See also [Backup strategies](https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md).
| Required | Path | Description |
| :------------- | :------------- | :-------------|
| ✅ | `:/home/pi/pialert/config` | Folder which will contain the `pialert.conf` file (see below for details) |
| ✅ | `:/home/pi/pialert/db` | Folder which will contain the `pialert.db` file |
| | `:/home/pi/pialert/front/log` | Logs folder useful for debugging if you have issues setting up the container |
| ✅ | `:/app/config` | Folder which will contain the `app.conf` & `devices.csv` ([read about devices.csv](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md)) files (see below for details). |
| ✅ | `:/app/db` | Folder which will contain the `app.db` file |
| | `:/app/front/log` | Logs folder useful for debugging if you have issues setting up the container |
| | `:/etc/pihole/pihole-FTL.db` | PiHole's `pihole-FTL.db` database file. Required if you want to use PiHole DB mapping. |
| | `:/etc/pihole/dhcp.leases` | PiHole's `dhcp.leases` file. Required if you want to use PiHole `dhcp.leases` file. This has to be matched with a corresponding `DHCPLSS_paths_to_check` setting entry (the path in the container must contain `pihole`)|
| | `:/home/pi/pialert/front/api` | A simple [API endpoint](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md) containing static (but regularly updated) json and other files. |
| | `:/home/pi/pialert/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/Pi.Alert/blob/main/front/plugins/README.md). |
| | `:/etc/resolv.conf` | Use a custom `resolv.conf` file for [better name resolution](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/REVERSE_DNS.md). |
| | `:/app/front/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). |
| | `:/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, don't nest them.
### Modify the config (`pialert.conf`) only if UI is not available
### (If UI is not available) Modify the config (`app.conf`)
- The preferred way is to manage the configuration via the Settings section in the UI.
- You can modify [pialert.conf](https://github.com/jokob-sk/Pi.Alert/tree/main/config) directly, if needed.
- If unavailable, the app generates a default `pialert.conf` and `pialert.db` file on the first run.
- You can modify [app.conf](https://github.com/jokob-sk/NetAlertX/tree/main/config) directly, if needed.
- If unavailable, the app generates a default `app.conf` and `app.db` file on the first run.
#### Important settings
@@ -69,7 +72,7 @@ These are the most important settings to get at least some output in your Device
##### For arp-scan: ARPSCAN_RUN, SCAN_SUBNETS
- ❗ To use the arp-scan method, you need to set the `SCAN_SUBNETS` variable. See the documentation on how [to setup SUBNETS, VLANs & limitations](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SUBNETS.md)
- ❗ To use the arp-scan method, you need to set the `SCAN_SUBNETS` variable. See the documentation on how [to setup SUBNETS, VLANs & limitations](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md)
##### For pihole: PIHOLE_RUN, DHCPLSS_RUN
@@ -105,12 +108,12 @@ Use the official installation guides at first and use community content as suple
### **Common issues**
💡 Before creating a new issue, please check if a similar issue was [already resolved](https://github.com/jokob-sk/Pi.Alert/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/Pi.Alert/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).
> [!NOTE]
> You can bulk-update devices via the [CSV import method](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEVICES_BULK_EDITING.md).
> You can bulk-update devices via the [CSV import method](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md).
## 📄 docker-compose.yml Examples
@@ -119,22 +122,20 @@ Use the official installation guides at first and use community content as suple
```yaml
version: "3"
services:
pialert:
container_name: pialert
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/pi.alert_dev:latest"
image: "jokobsk/pi.alert:latest"
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/pialert/config:/home/pi/pialert/config
- local/path/pialert/db:/home/pi/pialert/db
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/home/pi/pialert/front/log
- local/path/logs:/app/front/log
environment:
- TZ=Europe/Berlin
- HOST_USER_ID=1000
- HOST_USER_GID=1000
- PORT=20211
```
@@ -145,19 +146,19 @@ To run the container execute: `sudo docker-compose up -d`
Example by [SeimuS](https://github.com/SeimusS).
```yaml
pialert:
container_name: PiAlert
hostname: PiAlert
netalertx:
container_name: NetAlertX
hostname: NetAlertX
privileged: true
# use the below line if you want to test the latest dev image
# image: "jokobsk/pi.alert_dev:latest"
image: jokobsk/pi.alert:latest
# image: "jokobsk/netalertx-dev:latest"
image: jokobsk/netalertx:latest
environment:
- TZ=Europe/Bratislava
restart: always
volumes:
- ./pialert/pialert_db:/home/pi/pialert/db
- ./pialert/pialert_config:/home/pi/pialert/config
- ./netalertx/db:/app/db
- ./netalertx/config:/app/config
network_mode: host
```
@@ -170,22 +171,20 @@ To run the container execute: `sudo docker-compose up -d`
```yaml
version: "3"
services:
pialert:
container_name: pialert
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "jokobsk/pi.alert_dev:latest"
image: "jokobsk/pi.alert:latest"
# image: "jokobsk/netalertx-dev:latest"
image: "jokobsk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
- ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
- ${APP_DATA_LOCATION}/netalertx/config:/app/config
- ${APP_DATA_LOCATION}/netalertx/db/:/app/db/
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
- ${LOGS_LOCATION}:/app/front/log
environment:
- TZ=${TZ}
- HOST_USER_ID=${HOST_USER_ID}
- HOST_USER_GID=${HOST_USER_GID}
- PORT=${PORT}
```
@@ -201,8 +200,6 @@ LOGS_LOCATION=/path/to/docker_logs
#ENVIRONMENT VARIABLES
TZ=Europe/Paris
HOST_USER_ID=1000
HOST_USER_GID=1000
PORT=20211
#DEVELOPMENT VARIABLES
@@ -214,13 +211,13 @@ 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 `pialert_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.
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.
```yaml
pialert:
netalertx:
# use the below line if you want to test the latest dev image
# image: "jokobsk/pi.alert_dev:latest"
image: jokobsk/pi.alert
# image: "jokobsk/netalertx-dev:latest"
image: jokobsk/netalertx
ports:
- "80:20211/tcp"
environment:
@@ -230,22 +227,15 @@ Courtesy of [pbek](https://github.com/pbek). The volume `pialert_db` is used by
ipv4_address: 192.168.1.2
restart: unless-stopped
volumes:
- pialert_db:/home/pi/pialert/db
- ./pialert/pialert.conf:/home/pi/pialert/config/pialert.conf
- netalertx_db:/app/db
- ./netalertx/:/app/config/
```
## 🏅 Recognitions
Big thanks to <a href="https://github.com/Macleykun">@Macleykun</a> for help and tips&tricks for Dockerfile(s).
Big thanks to <a href="https://github.com/Macleykun">@Macleykun</a> & for help and tips & tricks for Dockerfile(s) and <a href="https://github.com/vladaurosh">@vladaurosh</a> for Alpine re-base help.
## ❤ Support me
Get:
- Regular updates to keep your data and family safe 🔄
- Better and more functionality
- I don't get burned out and the app survives longer🔥🤯
- Quicker and better support with issues 🆘
- Less grumpy 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) |
| --- | --- | --- |
@@ -253,4 +243,4 @@ Get:
- Bitcoin: `1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM`
- Ethereum: `0x6e2749Cb42F4411bc98501406BdcD82244e3f9C7`
> 📧 Email me at [jokob@duck.com](mailto:jokob@duck.com?subject=PiAlert) if you want to get in touch or if I should add other sponsorship platforms.
> 📧 Email me at [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX) if you want to get in touch or if I should add other sponsorship platforms.

View File

@@ -1,232 +0,0 @@
[![Docker](https://img.shields.io/github/actions/workflow/status/jokob-sk/Pi.Alert/docker_prod.yml?label=Build&logo=GitHub)](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
[![GitHub Committed](https://img.shields.io/github/last-commit/jokob-sk/Pi.Alert?color=40ba12&label=Committed&logo=GitHub&logoColor=fff)](https://github.com/jokob-sk/Pi.Alert)
[![Docker Size](https://img.shields.io/docker/image-size/jokobsk/pi.alert?label=Tamaño&logo=Docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/pi.alert?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
[![Docker Pushed](https://img.shields.io/badge/dynamic/json?color=0aa8d2&logoColor=fff&label=Pushed&query=last_updated&url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fjokobsk%2Fpi.alert%2F&logo=docker&link=http://left&link=https://hub.docker.com/repository/docker/jokobsk/pi.alert)](https://hub.docker.com/r/jokobsk/pi.alert)
# 🐳 Una imagen docker para Pi.Alert
🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📑 [Instrucciones para Docker](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) | 🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/releases) | 📚 [Todos los Docs](https://github.com/jokob-sk/Pi.Alert/tree/main/docs)
<a href="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" width="300px" />
</a>
<a href="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/network.png" target="_blank">
<img src="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/network.png" width="300px" />
</a>
## 📕 Uso básico
- Tendrás que ejecutar el contenedor en la red del host, por ejemplo:
```yaml
docker run -d --rm --network=host \
-v local/path/pialert/config:/home/pi/pialert/config \
-v local/path/pialert/db:/home/pi/pialert/db \
-e TZ=Europe/Berlin \
-e PORT=20211 \
jokobsk/pi.alert:latest
```
- El escaneo inicial puede tardar hasta 15 minutos (con 50 dispositivos y MQTT). Los siguientes pueden durar entre 3 y 5 minutos, así que espere a que se ejecuten todos los escaneos.
### Variables de entorno Docker
| Variable | Descripción | Predeterminado |
| :------------- |:-------------| -----:|
| `PORT` |Puerto de la interfaz web | `20211` |
|`TZ` |Zona horaria para mostrar correctamente las estadísticas. Encuentre su zona horaria [aquí](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | `Europe/Berlin` |
|`HOST_USER_GID` |ID de usuario (UID) para asignar el usuario del contenedor a un usuario del servidor con suficientes permisos de lectura y escritura en los archivos asignados | `1000` |
|`HOST_USER_ID` |ID de grupo de usuarios (GID) para asignar el grupo de usuarios del contenedor a un grupo de usuarios del servidor con suficientes permisos de lectura y escritura en los archivos asignados | `1000` |
### Rutas Docker
| | Ruta | Descripción |
| :------------- | :------------- |:-------------|
| **Obligatorio** | `:/home/pi/pialert/config` | Carpeta que contendrá el archivo `pialert.conf` (para más detalles, véase más abajo) |
| **Obligatorio** | `:/home/pi/pialert/db` | Carpeta que contendrá el archivo `pialert.db` |
|Opcional| `:/home/pi/pialert/front/log` | Carpeta de registros útil para depurar si tiene problemas al configurar el contenedor |
|Opcional| `:/etc/pihole/pihole-FTL.db` | Archivo de base de datos `pihole-FTL.db` de PiHole. Necesario si desea utilizar PiHole |
|Opcional| `:/etc/pihole/dhcp.leases` | Archivo `dhcp.leases` de PiHole. Obligatorio si desea utilizar el archivo `dhcp.leases` de PiHole. Tiene que coincidir con la correspondiente entrada de configuración `DHCPLSS_paths_to_check`. (La ruta en el contenedor debe contener `pihole`)|
|Opcional| `:/home/pi/pialert/front/api` | Una simple [API endpoint](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md) que contiene archivos json estáticos (pero actualizados regularmente) y otros archivos. |
### Configurar (`pialert.conf`)
- Si no está disponible, la aplicación genera un archivo `pialert.conf` y `pialert.db` por defecto en la primera ejecución.
- La forma preferida es gestionar la configuración a través de la sección "Configuración" de la interfaz de usuario.
- Puede modificar [pialert.conf](https://github.com/jokob-sk/Pi.Alert/tree/main/config) directamente, si es necesario.
#### Ajustes importantes
Estos son los ajustes más importantes para obtener al menos alguna salida en la pantalla de tus Dispositivos. Por lo general, sólo se utiliza un enfoque, pero usted debe ser capaz de combinar estos enfoques.
##### Para arp-scan: ARPSCAN_RUN, SCAN_SUBNETS
- ❗ Para usar el método arp-scan, necesitas configurar la variable `SCAN_SUBNETS`. Consulte la documentación sobre cómo [configurar SUBNETS, VLANs y limitaciones](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SUBNETS.md)
##### Para pihole: PIHOLE_RUN, DHCPLSS_RUN
Hay dos maneras de importar dispositivos PiHole. A través del plugin de importación PiHole (PIHOLE) o del plugin DHCP leases (DHCPLSS).
**PiHole (Sincronización de dispositivos)**
* `PIHOLE_RUN`: Necesitas mapear `:/etc/pihole/pihole-FTL.db` en el fichero `docker-compose.yml` si activas esta opción.
**DHCP Leases (Importación de dispositivos)**
* `DHCPLSS_RUN`: Es necesario mapear `:/etc/pihole/dhcp.leases` en el fichero `docker-compose.yml` si se activa esta opción.
* La configuración anterior tiene que coincidir con una entrada de configuración correspondiente `DHCPLSS_paths_to_check` (la ruta en el contenedor debe contener `pihole` ya que PiHole utiliza un formato diferente del archivo `dhcp.leases`).
> Se recomienda utilizar el mismo intervalo de programación para todos los plugins responsables de descubrir nuevos dispositivos.
### **Problemas comunes**
💡 Antes de crear una nueva incidencia, comprueba si ya se ha resuelto una [incidencia similar](https://github.com/jokob-sk/Pi.Alert/issues?q=is%3Aissue+is%3Aclosed).
⚠ Compruebe también los problemas comunes y los [consejos de depuración](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEBUG_TIPS.md).
## 📄 Ejemplos
### Ejemplo 1
```yaml
version: "3"
services:
pialert:
container_name: pialert
# Utilice la siguiente línea si desea probar la última imagen de desarrollo
# image: "jokobsk/pi.alert_dev:latest"
image: "jokobsk/pi.alert:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/pialert/config:/home/pi/pialert/config
- local/path/pialert/db:/home/pi/pialert/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/home/pi/pialert/front/log
environment:
- TZ=Europe/Berlin
- HOST_USER_ID=1000
- HOST_USER_GID=1000
- PORT=20211
```
Para ejecutar el contenedor ejecute: `sudo docker-compose up -d`
### Ejemplo 2
Ejemplo de [SeimuS](https://github.com/SeimusS).
```yaml
pialert:
container_name: PiAlert
hostname: PiAlert
privileged: true
# Utilice la siguiente línea si desea probar la última imagen de desarrollo
# image: "jokobsk/pi.alert_dev:latest"
image: jokobsk/pi.alert:latest
environment:
- TZ=Europe/Bratislava
restart: always
volumes:
- ./pialert/pialert_db:/home/pi/pialert/db
- ./pialert/pialert_config:/home/pi/pialert/config
network_mode: host
```
Para ejecutar el contenedor ejecute: `sudo docker-compose up -d`
### Ejemplo 3
`docker-compose.yml`
```yaml
version: "3"
services:
pialert:
container_name: pialert
# Utilice la siguiente línea si desea probar la última imagen de desarrollo
# image: "jokobsk/pi.alert_dev:latest"
image: "jokobsk/pi.alert:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
- ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
environment:
- TZ=${TZ}
- HOST_USER_ID=${HOST_USER_ID}
- HOST_USER_GID=${HOST_USER_GID}
- PORT=${PORT}
```
`.env` file
```yaml
#VARIABLES DE RUTA GLOBAL
APP_DATA_LOCATION=/path/to/docker_appdata
APP_CONFIG_LOCATION=/path/to/docker_config
LOGS_LOCATION=/path/to/docker_logs
#VARIABLES DE ENTORNO
TZ=Europe/Paris
HOST_USER_ID=1000
HOST_USER_GID=1000
PORT=20211
#VARIABLES DE DESARROLLO
DEV_LOCATION=/path/to/local/source/code
```
Para ejecutar el contenedor ejecute: `sudo docker-compose --env-file /path/to/.env up`
### Example 4
Por cortesía de [pbek](https://github.com/pbek). El volumen `pialert_db` es utilizado por el directorio db. Los dos archivos de configuración se montan directamente desde una carpeta local a sus lugares en la carpeta config. Puedes hacer una copia de seguridad de la carpeta `docker-compose.yaml` y de la carpeta docker volumes.
```yaml
pialert:
# Utilice la siguiente línea si desea probar la última imagen de desarrollo
# image: "jokobsk/pi.alert_dev:latest"
image: jokobsk/pi.alert
ports:
- "80:20211/tcp"
environment:
- TZ=Europe/Vienna
networks:
local:
ipv4_address: 192.168.1.2
restart: unless-stopped
volumes:
- pialert_db:/home/pi/pialert/db
- ./pialert/pialert.conf:/home/pi/pialert/config/pialert.conf
```
## 🏅 Reconocimientos
Muchas gracias a <a href="https://github.com/Macleykun">@Macleykun</a> por ayudarme en consejos y trucos para Dockerfile(s):
<a href="https://github.com/Macleykun">
<img src="https://avatars.githubusercontent.com/u/26381427?size=50">
</a>
Muchas gracias a <a href="https://github.com/cvc90">@cvc90</a> por ayudarme y realizar esta traduccion:
<a href="https://github.com/cvc90">
<img src="https://avatars.githubusercontent.com/u/76731844?size=50">
</a>
## ☕ Apóyame
<a href="https://github.com/sponsors/jokob-sk" target="_blank"><img src="https://i.imgur.com/X6p5ACK.png" alt="Sponsor Me on GitHub" style="height: 30px !important;width: 117px !important;" width="150px" ></a>
<a href="https://www.buymeacoffee.com/jokobsk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 117px !important;" width="117px" height="30px" ></a>
<a href="https://www.patreon.com/user?u=84385063" target="_blank"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" alt="Support me on patreon" style="height: 30px !important;width: 117px !important;" width="117px" ></a>
BTC: 1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM

41
dockerfiles/pre-setup.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
export INSTALL_DIR=/app
export APP_NAME=netalertx
# php-fpm setup
install -d -o nginx -g www-data /run/php/
sed -i "/^;pid/c\pid = /run/php/php8.2-fpm.pid" /etc/php82/php-fpm.conf
sed -i "/^listen/c\listen = /run/php/php8.2-fpm.sock" /etc/php82/php-fpm.d/www.conf
sed -i "/^;listen.owner/c\listen.owner = nginx" /etc/php82/php-fpm.d/www.conf
sed -i "/^;listen.group/c\listen.group = www-data" /etc/php82/php-fpm.d/www.conf
sed -i "/^user/c\user = nginx" /etc/php82/php-fpm.d/www.conf
sed -i "/^group/c\group = www-data" /etc/php82/php-fpm.d/www.conf
# s6 overlay setup
mkdir -p /etc/s6-overlay/s6-rc.d/{SetupOneshot,php-fpm/dependencies.d,nginx/dependencies.d}
mkdir -p /etc/s6-overlay/s6-rc.d/{SetupOneshot,php-fpm/dependencies.d,nginx/dependencies.d,$APP_NAME/dependencies.d}
echo "oneshot" > /etc/s6-overlay/s6-rc.d/SetupOneshot/type
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/setup.sh" > /etc/s6-overlay/s6-rc.d/SetupOneshot/up
echo -e "#!/bin/execlineb -P\n/usr/sbin/php-fpm82 -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
with-contenv
importas -u PORT PORT
if { echo
"
[INSTALL] 🚀 Starting app (:${PORT})
" }' > /etc/s6-overlay/s6-rc.d/$APP_NAME/run
echo -e "python ${INSTALL_DIR}/server" >> /etc/s6-overlay/s6-rc.d/$APP_NAME/run
touch /etc/s6-overlay/s6-rc.d/user/contents.d/{SetupOneshot,php-fpm,nginx} /etc/s6-overlay/s6-rc.d/{php-fpm,nginx}/dependencies.d/SetupOneshot
touch /etc/s6-overlay/s6-rc.d/user/contents.d/{SetupOneshot,php-fpm,nginx,$APP_NAME} /etc/s6-overlay/s6-rc.d/{php-fpm,nginx,$APP_NAME}/dependencies.d/SetupOneshot
touch /etc/s6-overlay/s6-rc.d/nginx/dependencies.d/php-fpm
touch /etc/s6-overlay/s6-rc.d/$APP_NAME/dependencies.d/nginx
rm -f $0

115
dockerfiles/setup.sh Executable file
View File

@@ -0,0 +1,115 @@
#!/usr/bin/with-contenv bash
echo "---------------------------------------------------------"
echo "[INSTALL] Run setup.sh"
echo "---------------------------------------------------------"
export INSTALL_DIR=/app # Specify the installation directory here
# DO NOT CHANGE ANYTHING BELOW THIS LINE!
CONF_FILE="app.conf"
NGINX_CONF_FILE=netalertx.conf
DB_FILE="app.db"
FULL_FILEDB_PATH="${INSTALL_DIR}/db/${DB_FILE}"
NGINX_CONFIG_FILE="/etc/nginx/http.d/${NGINX_CONF_FILE}"
OUI_FILE="/usr/share/arp-scan/ieee-oui.txt" # Define the path to ieee-oui.txt and ieee-iab.txt
INSTALL_DIR_OLD=/home/pi/pialert
OLD_APP_NAME=pialert
# DO NOT CHANGE ANYTHING ABOVE THIS LINE!
# Check if script is run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Please use 'sudo'."
exit 1
fi
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"
# Delete content of "$INSTALL_DIR/config/"
rm -rf "$INSTALL_DIR/config/"*
rm -rf "$INSTALL_DIR_OLD/config/"*
# Delete content of "$INSTALL_DIR/db/"
rm -rf "$INSTALL_DIR/db/"*
rm -rf "$INSTALL_DIR_OLD/db/"*
fi
# 🔻 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2024
# Check if pialert.db exists, then create a symbolic link to app.db
if [ -f "${INSTALL_DIR_OLD}/db/${OLD_APP_NAME}.db" ]; then
ln -s "${INSTALL_DIR_OLD}/db/${OLD_APP_NAME}.db" "${FULL_FILEDB_PATH}"
fi
# Check if ${OLD_APP_NAME}.conf exists, then create a symbolic link to app.conf
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
# Copy starter .db and .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}"
# if custom variables not set we do not need to do anything
if [ -n "${TZ}" ]; then
FILECONF="${INSTALL_DIR}/config/${CONF_FILE}"
echo "[INSTALL] Setup timezone"
sed -i "\#^TIMEZONE=#c\TIMEZONE='${TZ}'" "${FILECONF}"
# set TimeZone in container
cp /usr/share/zoneinfo/$TZ /etc/localtime
echo $TZ > /etc/timezone
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}"
# Run the hardware vendors update at least once
echo "[INSTALL] Run the hardware vendors update"
# Check if ieee-oui.txt or ieee-iab.txt exist
if [ -f "${OUI_FILE}" ]; then
echo "The file ieee-oui.txt exists. Skipping update_vendors.sh..."
else
echo "The file ieee-oui.txt does not exist. Running update_vendors..."
# Run the update_vendors.sh script
if [ -f "${INSTALL_DIR}/back/update_vendors.sh" ]; then
"${INSTALL_DIR}/back/update_vendors.sh"
else
echo "update_vendors.sh script not found in ${INSTALL_DIR}."
fi
fi
# Create an empty log files
# Create the execution_queue.log and app_front.log files if they don't exist
touch "${INSTALL_DIR}"/front/log/{app.log,execution_queue.log,app_front.log,app.php_errors.log,stderr.log,stdout.log}
echo "[INSTALL] Fixing permissions after copied starter config & DB"
chown -R nginx:www-data "${INSTALL_DIR}"/{config,front/log,db}
chmod 750 "${INSTALL_DIR}"/{config,front/log,db}
find "${INSTALL_DIR}"/{config,front/log,db} -type f -exec chmod 640 {} \;
# Check if buildtimestamp.txt doesn't exist
if [ ! -f "${INSTALL_DIR}/front/buildtimestamp.txt" ]; then
# Create buildtimestamp.txt
date +%s > "${INSTALL_DIR}/front/buildtimestamp.txt"
chown nginx:www-data "${INSTALL_DIR}/front/buildtimestamp.txt"
fi
echo -e "
[ENV] PATH is ${PATH}
[ENV] PORT is ${PORT}
[ENV] TZ is ${TZ}
[ENV] LISTEN_ADDR is ${LISTEN_ADDR}
[ENV] ALWAYS_FRESH_INSTALL is ${ALWAYS_FRESH_INSTALL}
"

View File

@@ -1,6 +1,6 @@
## API endpoints
PiAlert comes with a simple API. These API endpoints are static files, that are periodically updated based on your settings.
NetAlertX comes with a simple API. These API endpoints are static files, that are periodically updated based on your settings.
### When are the endpoints updated
@@ -9,7 +9,7 @@ The endpoints are updated when objects in the API endpoints are changed.
### Location of the endpoints
In the container, these files are located under the `/home/pi/pialert/front/api/` folder and thus on the `<pialert_url>/api/<File name>` url.
In the container, these files are located under the `/app/front/api/` folder and thus on the `<netalertx_url>/api/<File name>` url.
### Available endpoints
@@ -19,12 +19,12 @@ You can access the following files:
|----------------------|----------------------|
| `notification_text.txt` | The plain text version of the last notification. |
| `notification_text.html` | The full HTML of the last email notification. |
| `notification_json_final.json` | The json version of the last notification (e.g. used for webhooks - [sample JSON](https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json)). |
| `notification_json_final.json` | The json version of the last notification (e.g. used for webhooks - [sample JSON](https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json)). |
| `table_devices.json` | The current (at the time of the last update as mentioned above on this page) state of all of the available Devices detected by the app. |
| `table_pholus_scan.json` | The latest state of the [pholus](https://github.com/jokob-sk/Pi.Alert/tree/main/pholus) (A multicast DNS and DNS Service Discovery Security Assessment Tool) scan results. |
| `table_pholus_scan.json` | The latest state of the [pholus](https://github.com/jokob-sk/NetAlertX/tree/main/pholus) (A multicast DNS and DNS Service Discovery Security Assessment Tool) scan results. |
| `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/Pi.Alert/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/front/plugins)|
| `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. |

82
docs/BACKUPS.md Executable file
View File

@@ -0,0 +1,82 @@
# 💾 Backing things up
> [!NOTE]
> To backup 99% of your configuration backup at least the `/config` folder. Please read the whole page (or at least "Scenario 2: Corrupted database") for details.
There are 3 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 | Doesn't contain settings from the Maintenance section |
| `/config/devices.csv` | CSV file containing device information | Doesn't contain historical data |
## Data and cackup storage
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:
- Notification settings
- Scanner settings
- Scheduled maintenance settings
- UI configuration (80%)
### Core Device Data
The core device data is backed up to the `devices_<timestamp>.csv` file via the [CSV Backup `CSVBCKP` Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup). This file contains data, such as:
- Device names
- Device Icons
- Device Network configuration
- Device categorization
### 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:
- 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` file, followed by the `app.conf` file.
### Scenario 1: Full backup
End-result: Full restore
#### Source artifacts:
- `/db/app.db` (uncorrupted)
- `/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:
- `/config/app.conf`
- `/config/devices_<timestamp>.csv` or `/config/devices.csv`
#### Recovery:
Even with a corrupted database you can recover what I would argue is 99% of the configuration (except of a couple of settings under Maintenance).
- map the `/config/app.conf` file 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 `/config` folder
- Restore the `devices.csv` backup via the [Maintenance section](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md)

View File

@@ -1,5 +1,5 @@
# A high-level description of the datbase structure
# 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.
@@ -20,7 +20,7 @@
| Plugins_Language_Strings | Language strings colelcted from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] |
| Plugins_Objects | Unique objects detected by individual plugins. | ![Screen13][screen13] |
| Sessions | Used to display sessions in the charts | ![Screen15][screen15] |
| Settings | Database representation of the sum of all settings from `pialert.conf` and plugins coming from `config.json` files. | ![Screen16][screen16] |
| Settings | Database representation of the sum of all settings from `app.conf` and plugins coming from `config.json` files. | ![Screen16][screen16] |

View File

@@ -8,9 +8,9 @@ Check the the HTTP response of the failing backend call by following these steps
![F12DeveloperConsole][F12DeveloperConsole]
- Copy the URL causing the error and enter it in the address bar of your browser directly and hit enter. The copied URLs could look something like this (notice the query strings at the end):
- `http://<pialert URL>:20211/api/table_devices.json?nocache=1704141103121`
- `http://<pialert URL>:20211/php/server/devices.php?action=getDevicesTotals`
- `http://<pialert URL>:20211/php/server/devices.php?action=getDevicesList&status=all`
- `http://<NetAlertX URL>:20211/api/table_devices.json?nocache=1704141103121`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesTotals`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesList&status=all`
- Post the error response in the existing issue thread on GitHub or create a new issue and include the redacted response of the failing query.

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/Pi.Alert/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/front/plugins/README.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/Pi.Alert/blob/main/docs/DEBUG_TIPS.md#1-more-logging-)
- Ensure you have [debug enabled (see More Logging)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md#1-more-logging-)
### Potential issues
@@ -19,7 +19,7 @@ For a more in-depth overview on how plugins work check the [Plugins development
#### Incorrect input data
Input data from the plugin might cause mapping issues in specific edge cases. Look for a corresponding section in the `pialert.log` file, for example notice the first line of the execution run of the `PIHOLE` plugin below:
Input data from the plugin might cause mapping issues in specific edge cases. Look for a corresponding section in the `app.log` file, for example notice the first line of the execution run of the `PIHOLE` plugin below:
```
17:31:05 [Scheduler] - Scheduler run for PIHOLE: YES
@@ -35,6 +35,7 @@ Input data from the plugin might cause mapping issues in specific edge cases. Lo
17:31:05 [Plugins] base64 value: b'MTkyLjE2OC4xLjAvMjQgLS1pbnRlcmZhY2U9ZXRoMQ=='
17:31:05 [Plugins] Timeout: 10
17:31:05 [Plugins] Executing: SELECT n.hwaddr AS Object_PrimaryID, 'null' AS Object_SecondaryID, datetime() AS DateTime, na.ip AS Watched_Value1, n.lastQuery AS Watched_Value2, na.name AS Watched_Value3, n.macVendor AS Watched_Value4, 'null' AS Extra, n.hwaddr AS ForeignKey FROM EXTERNAL_PIHOLE.Network AS n LEFT JOIN EXTERNAL_PIHOLE.Network_Addresses AS na ON na.network_id = n.id WHERE n.hwaddr NOT LIKE 'ip-%' AND n.hwaddr is not '00:00:00:00:00:00' AND na.ip is not null
🔻
17:31:05 [Plugins] SUCCESS, received 2 entries
17:31:05 [Plugins] sqlParam entries: [(0, 'PIHOLE', '01:01:01:01:01:01', 'null', 'null', '2023-12-25 06:31:05', '172.30.0.1', 0, 'aaaa', 'vvvvvvvvv', 'not-processed', 'null', 'null', '01:01:01:01:01:01'), (0, 'PIHOLE', '02:42:ac:1e:00:02', 'null', 'null', '2023-12-25 06:31:05', '172.30.0.2', 0, 'dddd', 'vvvvv2222', 'not-processed', 'null', 'null', '02:42:ac:1e:00:02')]
17:31:05 [Plugins] Processing : PIHOLE
@@ -52,10 +53,13 @@ Input data from the plugin might cause mapping issues in specific edge cases. Lo
17:31:05 [Plugins] Mapping objects to database table: CurrentScan
17:31:05 [Plugins] SQL query for mapping: INSERT into CurrentScan ( "cur_MAC", "cur_IP", "cur_LastQuery", "cur_Name", "cur_Vendor", "cur_ScanMethod") VALUES ( ?, ?, ?, ?, ?, ?)
17:31:05 [Plugins] SQL sqlParams for mapping: [('01:01:01:01:01:01', '172.30.0.1', 0, 'aaaa', 'vvvvvvvvv', 'PIHOLE'), ('02:42:ac:1e:00:02', '172.30.0.2', 0, 'dddd', 'vvvvv2222', 'PIHOLE')]
🔺
17:31:05 [API] Update API starting
17:31:06 [API] Updating table_plugins_history.json file in /front/api
```
> The debug output between the 🔻red arrows🔺 is important for debugging (arrows added only to highlight the section on this page, they are not available in the actual debug log)
In the above output notice the section logging how many events are produced by the plugin:
```

View File

@@ -15,11 +15,11 @@ Start the container via the **terminal** with a command similar to this one:
```bash
docker run --rm --network=host \
-v local/path/pialert/config:/home/pi/pialert/config \
-v local/path/pialert/db:/home/pi/pialert/db \
-v local/path/netalertx/config:/app/config \
-v local/path/netalertx/db:/app/db \
-e TZ=Europe/Berlin \
-e PORT=20211 \
jokobsk/pi.alert:latest
jokobsk/netalertx:latest
```
@@ -29,11 +29,11 @@ docker run --rm --network=host \
If possible, check if your issue got fixed in the `_dev` image before opening a new issue. The container is:
`jokobsk/pi.alert_dev:latest`
`jokobsk/netalertx-dev:latest`
> ⚠ Please backup your DB and config beforehand!
Please also search [open issues](https://github.com/jokob-sk/Pi.Alert/issues).
Please also search [open issues](https://github.com/jokob-sk/NetAlertX/issues).
## 4. Disable restart behavior 🛑
@@ -53,10 +53,9 @@ services:
### 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 `/home/pi/pialert/front/log`.
* To solve permission issues you can try setting the owner and group of the `pialert.db` by executing the following on the host system: `docker exec pialert chown -R www-data:www-data /home/pi/pialert/db/pialert.db`.
* Map to local User and Group IDs. Specify the enviroment variables `HOST_USER_ID` and `HOST_USER_GID` if needed.
* If still facing issues, try to map the pialert.db file (⚠ not folder) to `:/home/pi/pialert/db/pialert.db` (see [docker-compose Examples](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md#-docker-composeyml-examples) for details)
* 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/front/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

View File

@@ -1,16 +1,26 @@
# 🖊 Multi-editing via the UI
> [!NOTE]
> Make sure you have your backups saved and restorable before doing any mass edits. Check [Backup strategies](/docs/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)
# 📝Bulk-edit devices via CSV Export/Import
> [!NOTE]
> As always, backup everything, just in case.
1. In `Maintenance` > `Backup / Restore` click the `CSV Export` button.
1. In _Maintenance_ > _Backup / Restore_ click the _CSV Export_ button.
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)
> [!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 pialert url>/php/server/devices.php?action=ExportCSV` or via the `CSV Backup` plugin. (💡 You can schedule this)
> 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)

View File

@@ -1,4 +1,4 @@
# Pi.Alert - Device Management
# NetAlertX - Device Management
<!--- --------------------------------------------------------------------- --->
To edit device information:
- Select "Devices" in the menu on the left of the screen
@@ -11,7 +11,7 @@ To edit device information:
> [!NOTE]
>
> [Bulk-edit devices](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEVICES_BULK_EDITING.md) by using the `CSV Export` functionality in the `Maintenance` section.
> [Bulk-edit devices](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md) by using the _CSV Export_ functionality in the _Maintenance_ section.
![Device Details][screen1]
@@ -23,7 +23,7 @@ To edit device information:
- **Owner**: Device owner (The list is self-populated with existing owners)
- **Type**: Select a device type from the dropdown list (Smartphone, Table,
Laptop, TV, router, ....) or type a new device type
- **Vendor**: Automatically updated by Pi.Alert when empty or unknown
- **Vendor**: Automatically updated by NetAlertX when empty or unknown
- **Favorite**: Mark the device as favorite and then it will appears at the
begining of the device list
- **Group**: Select a grouper ('Always on', 'Personal', Friends') or type
@@ -66,7 +66,7 @@ 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, Pi.Alert will be able to identify the device, and it
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).
@@ -89,11 +89,11 @@ decides to change the MAC).
Always use the Issue tracker for the correct fork, for example:
[jokob-sk/Pi.Alert](https://github.com/jokob-sk/Pi.Alert/issues). Please also follow the guidelines on:
[jokob-sk/NetAlertX](https://github.com/jokob-sk/NetAlertX/issues). Please also follow the guidelines on:
- [Pull Request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-pull-requests-prs)
- 🙏 [Feature request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-feature-requests)
- 🐛 [Issue guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-submitting-an-issue-or-bug)
- [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***

View File

@@ -1,6 +1,6 @@
# 🖼 Frontend development
This page contains tips for frontend development when extending PiAlert. Guiding principles are:
This page contains tips for frontend development when extending NetAlertX. Guiding principles are:
1. Maintainability
2. Extendability
@@ -43,4 +43,4 @@ Some useful frontend JavaScript functions:
- `getSetting(string stringKey)` - method to retrieve settings in the frontend
Check the [pialert_common.js](https://github.com/jokob-sk/Pi.Alert/blob/main-2023-06-10/front/js/pialert_common.js) file for more frontend functions.
Check the [common.js](https://github.com/jokob-sk/NetAlertX/blob/main-2023-06-10/front/js/common.js) file for more frontend functions.

View File

@@ -1,6 +1,6 @@
# Overview
PiAlert comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
## ⚠ Note
@@ -16,17 +16,18 @@ PiAlert comes with MQTT support, allowing you to show all detected devices as de
2. Configure a user name and password on your broker.
3. Note down the following details that you will need to configure PiAlert:
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. Ope the `PiAlert` > `Settings` > `MQTT` settings group
4. Open the _NetAlertX_ > _Settings_ > _MQTT_ settings group
- Enable MQTT
- Fill in the details from above
- Fill in remaining settings as per description
![Configuration Example][configuration]
## 📷 Screenshots
@@ -35,8 +36,9 @@ PiAlert comes with MQTT support, allowing you to show all detected devices as de
| ![Screen 3][list] | ![Screen 4][overview] |
[sensors]: /docs/img/HOME_ASISSTANT/PiAlert-HomeAssistant-Device-as-Sensors.png "sensors"
[history]: /docs/img/HOME_ASISSTANT/PiAlert-HomeAssistant-Device-Presence-History.png "history"
[list]: /docs/img/HOME_ASISSTANT/PiAlert-HomeAssistant-Devices-List.png "list"
[overview]: /docs/img/HOME_ASISSTANT/PiAlert-HomeAssistant-Overview-Card.png "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"

View File

@@ -1,49 +1,49 @@
# How to install PiAlert on the server hardware
# How to install NetAlertX on the server hardware
To download and install PiAlert on the hardware/server directly use the `curl` or `wget` commands at the bottom of this page.
To download and install NetAlertX on the hardware/server directly use the `curl` or `wget` commands at the bottom of this page.
> [!NOTE]
> This is an Experimental feature 🧪 and it relies on community support.
>
> There is no guarantee that the install script or any other script will gracefully handle other installed software.
> Data loss is a possibility, **it is recommended to install PiAlert using the supplied Docker image**.
> Data loss is a possibility, **it is recommended to install NetAlertX using the supplied Docker image**.
A warning to the installation method below: Piping to bash is [controversial](https://pi-hole.net/2016/07/25/curling-and-piping-to-bash) and may
be dangerous, as you cannot see the code that's about to be executed on your system.
Alternatively you can download the installation script `install/install.sh` from the repository and check the code yourself (beware other scripts are
Alternatively you can download the installation script `install/install.debian.sh` from the repository and check the code yourself (beware other scripts are
downloaded too - only from this repo).
PiAlert will be installed in `home/pi/pialert/` and run on port number `20211`.
NetAlertX will be installed in `/app` and run on port number `20211`.
Some facts about what and where something will be changed/installed by the HW install setup (may not contain everything!):
- `/home/pi/pialert` directory will be deleted and newly created
- `/home/pi/pialert` will contain the whole repository (downloaded by `install/install.sh`)
- `/app` directory will be deleted and newly created
- `/app` will contain the whole repository (downloaded by `install/install.debian.sh`)
- The default NGINX site `/etc/nginx/sites-enabled/default` will be disabled (sym-link deleted or backed up to `sites-available`)
- `/var/www/html/pialert` directory will be deleted and newly created
- `/etc/nginx/conf.d/pialert.conf` will be sym-linked to `/home/pi/pialert/install/pialert.conf`
- `/var/www/html/netalertx` directory will be deleted and newly created
- `/etc/nginx/conf.d/netalertx.conf` will be sym-linked to `/app/install/netalertx.debian.conf`
- Some files (IEEE device vendors info, ...) will be created in the directory where the installation script is executed
## Limitations
- No system service is provided. PiAlert must be started using `/home/pi/pialert/dockerfiles/start.sh`.
- No system service is provided. NetAlertX must be started using `/app/install/start.debian.sh`.
- No checks for other running software is done.
- Only tested to work on Debian Bookworm (Debian 12).
- **EXPERIMENTAL** and not recommended way to install PiAlert.
- **EXPERIMENTAL** and not recommended way to install NetAlertX.
## 📥 Installation via CURL
```bash
curl -o install.sh https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/install/install.sh && sudo chmod +x install.sh && sudo ./install.sh
curl -o install.debian.sh https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/install/install.debian.sh && sudo chmod +x install.debian.sh && sudo ./install.debian.sh
```
## 📥 Installation via WGET
```bash
wget https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/install/install.sh -O install.sh && sudo chmod +x install.sh && sudo ./install.sh
wget https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/install/install.debian.sh -O install.debian.sh && sudo chmod +x install.debian.sh && sudo ./install.debian.sh
```
These commands will download the `install.sh` script from the GitHub repository, make it executable with `chmod`, and then run it using `./install.sh`.
These commands will download the `install.debian.sh` script from the GitHub repository, make it executable with `chmod`, and then run it using `./install.debian.sh`.
Make sure you have the necessary permissions to execute the script.

View File

@@ -1,32 +1,51 @@
## 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). Currently only free [Font Awesome](https://fontawesome.com/search?o=r&m=free) icons (up-to v 6.4.0) are supported.
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).
![Raspberry Pi with a brand icon](/docs/img/ICONS/devices-icons.png)
## ⚙ How to use custom device Icons
### Icons Support
Two types of icons are suported:
- Free [Font Awesome](https://fontawesome.com/search?o=r&m=free) icons (up-to v 6.4.0)
- SVG icons (for example from [iconify.design](https://icon-sets.iconify.design/))
You can assign icons individually on each device in the Details tab.
![preview](/docs/img/ICONS/device_icons_preview.gif)
## Adding new icons
![Raspberry Pi device details](/docs/img/ICONS/device-icon.png)
1. You can get an SVG or a Font awesome HTML code
- You can click into the `Icon` field or click the Pencil (2) icon in the above screenshot to enter any text. Only [free Font Awesome](https://fontawesome.com/search?o=r&m=free) icons in the following format will work:
Copying the SVG (for example from [iconify.design](https://icon-sets.iconify.design/)):
1. For any value that is only prefixed with `fa-`, you can enter the value directly, such as `server`, `tv`, `ethernet`.
2. If you want to add another classname, e.g. `fa-brands`, you can enter `brands fa-[fontawesome-icon-name]`, so for `apple` that is using the syntax`fa-brands fa-apple`, you would enter `brands fa-apple`.
![iconify svg](/docs/img/ICONS/iconify_design_copy_svg.png)
- If you want to mass-apply an icon to all devices of the same device type (Field marked (4) in the above screenshot), you can click the copy button (Marked (1) in the above screenshot). A confirmation prompt is displayed. If you proceed, icons of all devices set to the same device type as the current device, will be overwritten with the current device's icon.
Copying the HTML code from [Font Awesome](https://fontawesome.com/search?o=r&m=free).
- The dropdown (3) contains all icons already used in the app for device icons. You need to navigate away or refresh the page once you add a new icon.
![Font awesome](/docs/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)
3. Paste in the copied HTML or SVG code and click "OK":
![Paste SVG](/docs/img/ICONS/paste-svg.png)
6. "Save" the device
> [!NOTE]
> If you want to mass-apply an icon to all devices of the same device type (Field: Type), you can click the mass-copy button (next to the "+" button). A confirmation prompt is displayed. If you proceed, icons of all devices set to the same device type as the current device, will be overwritten with the current device's icon.
- The blue dropdown contains all icons already used in the app for device icons. You need to navigate away or refresh the page once you add a new icon.
## 🌟 Pro Font Awesome icons
If you own the premium package of Font Awesome icons you can mount it in your Docker container the following way:
```yaml
/font-awesome:/home/pi/pialert/front/lib/AdminLTE/bower_components/font-awesome:ro
/font-awesome:/app/front/lib/AdminLTE/bower_components/font-awesome:ro
```
You can use the full range of Font Awesome icons afterwards.

122
docs/MIGRATION.md Executable file
View File

@@ -0,0 +1,122 @@
# Migration form PiAlert to NetAlertX
> [!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. Even so, it's always good to have a [backup strategy](https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md) in place.
The migration should be pretty straightforward. The application installation folder in the docker container has changed from `/home/pi/pialert` to `/app`. That means the new mount points are:
| Old mount point | New mount point |
|----------------------|---------------|
| `/home/pi/pialert/config` | `/app/config` |
| `/home/pi/pialert/db` | `/app/db` |
If you were mounting files directly, please note the file names have changed:
| Old file name | New file name |
|----------------------|---------------|
| `pialert.conf` | `app.conf` |
| `pialert.db` | `app.db` |
> [!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.
In summary, docker file mount locations in your `docker-compose.yml` or docker run command have changed. Examples follow.
## 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: "jokobsk/pialert:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/home/pi/pialert/config
- local/path/db:/home/pi/pialert/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/home/pi/pialert/front/log
environment:
- TZ=Europe/Berlin
- PORT=20211
```
### 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)
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config # ⚠ This has changed (🔺required)
- local/path/db:/app/db # ⚠ This has changed (🔺required)
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/front/log # ⚠ This has changed (🟡optional)
environment:
- TZ=Europe/Berlin
- PORT=20211
```
## Example 2: Mapping files
> [!NOTE]
> The recommendation is to map folders as in Example 1, map files directly only when needed.
### 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: "jokobsk/pialert:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config/pialert.conf:/home/pi/pialert/config/pialert.conf
- local/path/db/pialert.db:/home/pi/pialert/db/pialert.db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/home/pi/pialert/front/log
environment:
- TZ=Europe/Berlin
- PORT=20211
```
### 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)
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config/app.conf:/app/config/app.conf # ⚠ This has changed (🔺required)
- local/path/db/app.db:/app/db/app.db # ⚠ This has changed (🔺required)
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/front/log # ⚠ This has changed (🟡optional)
environment:
- TZ=Europe/Berlin
- PORT=20211
```

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 [Undiscoverables plugin](https://github.com/jokob-sk/Pi.Alert/blob/main/front/plugins/undiscoverables/README.md)
> 💡 Tip: You can add dummy devices via the [Undiscoverables plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/undiscoverables/README.md)
> 💡 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](/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.
## 🔍Detailed example:

View File

@@ -12,7 +12,7 @@ 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, Pi.Alert will be able to identify the device, and it
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).
@@ -37,11 +37,11 @@ decides to change the MAC).
### Contact
Always use the Issue tracker for the correct fork, for example:
[jokob-sk/Pi.Alert](https://github.com/jokob-sk/Pi.Alert/issues). Please also follow the guidelines on:
[jokob-sk/NetAlertX](https://github.com/jokob-sk/NetAlertX/issues). Please also follow the guidelines on:
- [Pull Request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-pull-requests-prs)
- 🙏 [Feature request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-feature-requests)
- 🐛 [Issue guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-submitting-an-issue-or-bug)
- [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***

View File

@@ -13,11 +13,11 @@ There is also an in-app Help / FAQ section that should be answering frequently a
#### 🐳 Docker (Fully supported)
- The main installation method is as a [docker container - follow these instructions here](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md).
- The main installation method is as a [docker container - follow these instructions here](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md).
#### 💻 Bare-metal / On-server (Experimental/community supported 🧪)
- [(Experimental 🧪) On-hardware instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/HW_INSTALL.md)
- [(Experimental 🧪) On-hardware instructions](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md)
- Alternative bare-metal install forks:
- [leiweibau's fork](https://github.com/leiweibau/Pi.Alert/) (maintained)
@@ -32,6 +32,7 @@ There is also an in-app Help / FAQ section that should be answering frequently a
- [Custom Icon configuration and support](/docs/ICONS.md)
- [Better name resolution with Reverse DNS](/docs/REVERSE_DNS.md)
- [Network treemap configuration](/docs/NETWORK_TREE.md)
- [Backups](/docs/BACKUPS.md)
#### 🐛 Debugging help & tips
@@ -62,7 +63,7 @@ There is also an in-app Help / FAQ section that should be answering frequently a
#### 👩💻For Developers👨💻
- [APP code structure](/pialert/README.md)
- [Server APP code structure](/server/README.md)
- [Database structure](/docs/DATABASE.md)
- [API endpoints details](/docs/API.md)
- [Plugin system details and how to develop your own](/front/plugins/README.md)
@@ -82,7 +83,7 @@ Priorities from highest to lowest:
* 🔵 Refactoring enabling faster implementation of future functionality
* 🔽 (low) UI functionality & improvements (PRs welcome 😉)
Design philosophy: Focus on core functionality and leverage existing apps and tools to make PiAlert integrate into other workflows.
Design philosophy: Focus on core functionality and leverage existing apps and tools to make NetAlertX integrate into other workflows.
Examples:
@@ -106,7 +107,7 @@ If you submit a PR please:
1. Check that your changes are backward compatible with existing installations and with a blank setup.
2. Existing features should always be preserved.
3. Keep the PR small, on-topic and don't change code that is not necessary for the PR to work
4. New features code should ideally be re-usable for different purposes, not be for a very narrow use-case.
4. New features code should ideally be re-usable for different purposes, not for a very narrow use case.
5. New functionality should ideally be implemented via the Plugins system, if possible.
Suggested test cases:
@@ -121,15 +122,15 @@ Suggested test cases:
Some additional context:
* Permanent settings/config is stored in the `pialert.conf` file
* Permanent settings/config is stored in the `app.conf` file
* Currently temporary (session?) settings are stored in the `Parameters` DB table as key-value pairs. This table is wiped during a container rebuild/restart and its values are re-initialized from cookies/session data from the browser.
## 🐛 Submitting an issue or bug
Before submitting a new issue please spend a couple of minutes on research:
* Check [🛑 Common issues](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/DEBUG_TIPS.md#common-issues)
* Check [💡 Closed issues](https://github.com/jokob-sk/Pi.Alert/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/Pi.Alert/blob/main/docs/DEBUG_TIPS.md)❗
* Check [🛑 Common issues](https://github.com/jokob-sk/NetAlertX/blob/main/docs/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)❗
⚠ Please follow the pre-defined issue template to resolve your issue faster.

View File

@@ -1,6 +1,6 @@
## Setting up better name discovery with Reverse DNS
If you are running a DNS server, such as **AdGuard**, set up **Private reverse DNS servers** for a better name resolution on your network. Enabling this setting will enable PiAlert to execute dig and nslookup commands to automatically resolve device names based on their IP addresses.
If you are running a DNS server, such as **AdGuard**, set up **Private reverse DNS servers** for a better name resolution on your network. Enabling this setting will enable NetAlertX to execute dig and nslookup commands to automatically resolve device names based on their IP addresses.
> Example 1: Reverse DNS `disabled`
@@ -36,20 +36,18 @@ You can configure a custom **/etc/resolv.conf** file in **docker-compose.yml** a
```yaml
version: "3"
services:
pialert:
container_name: pialert
image: "jokobsk/pi.alert:latest"
netalertx:
container_name: netalertx
image: "jokobsk/netalertx:latest"
restart: unless-stopped
volumes:
- ./config/pialert.conf:/home/pi/pialert/config/pialert.conf
- ./pialert_db:/home/pi/pialert/db
- ./log:/home/pi/pialert/front/log
- ./config/app.conf:/app/config/app.conf
- ./db:/app/db
- ./log:/app/front/log
- ./config/resolv.conf:/etc/resolv.conf # Mapping the /resolv.conf file for better name resolution
environment:
- TZ=Europe/Berlin
- PORT=20211
- HOST_USER_ID=1000
- HOST_USER_GID=1000
ports:
- "20211:20211"
network_mode: host

View File

@@ -2,16 +2,20 @@
> Submitted by amazing [cvc90](https://github.com/cvc90) 🙏
> [!NOTE]
> There are 2 NGINX files for NetAlertX, one for the bare-metal Debian install (`netalertx.debian.conf`), and one for the docker container (`netalertx.template.conf`). Both can be found in the [install](https://github.com/jokob-sk/NetAlertX/tree/main/install) folder. Map, or use, the one appropriate for your setup.
## NGINX HTTP Configuration (Direct Path)
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 80;
server_name pi.alert;
server_name netalertx;
proxy_preserve_host on;
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
@@ -22,26 +26,26 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at http://pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at http://netalertx/
<br>
## NGINX HTTP Configuration (Sub Path)
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 80;
server_name pi.alert;
server_name netalertx;
proxy_preserve_host on;
location ^~ /pi.alert/ {
location ^~ /netalertx/ {
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
proxy_redirect ~^/(.*)$ /pi.alert/$1;
rewrite ^/pi.alert/?(.*)$ /$1 break;
proxy_redirect ~^/(.*)$ /netalertx/$1;
rewrite ^/netalertx/?(.*)$ /$1 break;
}
}
```
@@ -50,34 +54,34 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at http://pi.alert/pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at http://netalertx/netalertx/
<br>
## NGINX HTTP Configuration (Sub Path) with module ngx_http_sub_module
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 80;
server_name pi.alert;
server_name netalertx;
proxy_preserve_host on;
location ^~ /pi.alert/ {
location ^~ /netalertx/ {
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
proxy_redirect ~^/(.*)$ /pi.alert/$1;
rewrite ^/pi.alert/?(.*)$ /$1 break;
proxy_redirect ~^/(.*)$ /netalertx/$1;
rewrite ^/netalertx/?(.*)$ /$1 break;
sub_filter_once off;
sub_filter_types *;
sub_filter 'href="/' 'href="/pi.alert/';
sub_filter '(?>$host)/css' '/pi.alert/css';
sub_filter '(?>$host)/js' '/pi.alert/js';
sub_filter '/img' '/pi.alert/img';
sub_filter '/lib' '/pi.alert/lib';
sub_filter '/php' '/pi.alert/php';
sub_filter 'href="/' 'href="/netalertx/';
sub_filter '(?>$host)/css' '/netalertx/css';
sub_filter '(?>$host)/js' '/netalertx/js';
sub_filter '/img' '/netalertx/img';
sub_filter '/lib' '/netalertx/lib';
sub_filter '/php' '/netalertx/php';
}
}
```
@@ -86,23 +90,23 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at http://pi.alert/pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at http://netalertx/netalertx/
<br>
**NGINX HTTPS Configuration (Direct Path)**
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 443;
server_name pi.alert;
server_name netalertx;
SSLEngine On;
SSLCertificateFile /etc/ssl/certs/pi.alert.pem;
SSLCertificateKeyFile /etc/ssl/private/pi.alert.key;
SSLCertificateFile /etc/ssl/certs/netalertx.pem;
SSLCertificateKeyFile /etc/ssl/private/netalertx.key;
proxy_preserve_host on;
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
@@ -113,28 +117,28 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at https://pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at https://netalertx/
<br>
**NGINX HTTPS Configuration (Sub Path)**
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 443;
server_name pi.alert;
server_name netalertx;
SSLEngine On;
SSLCertificateFile /etc/ssl/certs/pi.alert.pem;
SSLCertificateKeyFile /etc/ssl/private/pi.alert.key;
location ^~ /pi.alert/ {
SSLCertificateFile /etc/ssl/certs/netalertx.pem;
SSLCertificateKeyFile /etc/ssl/private/netalertx.key;
location ^~ /netalertx/ {
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
proxy_redirect ~^/(.*)$ /pi.alert/$1;
rewrite ^/pi.alert/?(.*)$ /$1 break;
proxy_redirect ~^/(.*)$ /netalertx/$1;
rewrite ^/netalertx/?(.*)$ /$1 break;
}
}
```
@@ -143,36 +147,36 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at https://pi.alert/pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at https://netalertx/netalertx/
<br>
## NGINX HTTPS Configuration (Sub Path) with module ngx_http_sub_module
1. On your NGINX server, create a new file called /etc/nginx/sites-available/pialert
1. On your NGINX server, create a new file called /etc/nginx/sites-available/netalertx
2. In this file, paste the following code:
```
server {
listen 443;
server_name pi.alert;
server_name netalertx;
SSLEngine On;
SSLCertificateFile /etc/ssl/certs/pi.alert.pem;
SSLCertificateKeyFile /etc/ssl/private/pi.alert.key;
location ^~ /pi.alert/ {
SSLCertificateFile /etc/ssl/certs/netalertx.pem;
SSLCertificateKeyFile /etc/ssl/private/netalertx.key;
location ^~ /netalertx/ {
proxy_pass http://localhost:20211/;
proxy_pass_reverse http://localhost:20211/;
proxy_redirect ~^/(.*)$ /pi.alert/$1;
rewrite ^/pi.alert/?(.*)$ /$1 break;
proxy_redirect ~^/(.*)$ /netalertx/$1;
rewrite ^/netalertx/?(.*)$ /$1 break;
sub_filter_once off;
sub_filter_types *;
sub_filter 'href="/' 'href="/pi.alert/';
sub_filter '(?>$host)/css' '/pi.alert/css';
sub_filter '(?>$host)/js' '/pi.alert/js';
sub_filter '/img' '/pi.alert/img';
sub_filter '/lib' '/pi.alert/lib';
sub_filter '/php' '/pi.alert/php';
sub_filter 'href="/' 'href="/netalertx/';
sub_filter '(?>$host)/css' '/netalertx/css';
sub_filter '(?>$host)/js' '/netalertx/js';
sub_filter '/img' '/netalertx/img';
sub_filter '/lib' '/netalertx/lib';
sub_filter '/php' '/netalertx/php';
}
}
```
@@ -181,19 +185,19 @@
`nginx -s reload` or `systemctl restart nginx`
4. Once NGINX restarts, you should be able to access the proxy website at https://pi.alert/pi.alert/
4. Once NGINX restarts, you should be able to access the proxy website at https://netalertx/netalertx/
<br>
## Apache HTTP Configuration (Direct Path)
1. On your Apache server, create a new file called /etc/apache2/sites-available/pialert.conf.
1. On your Apache server, create a new file called /etc/apache2/sites-available/netalertx.conf.
2. In this file, paste the following code:
```
<VirtualHost *:80>
ServerName pi.alert
ServerName netalertx
ProxyPreserveHost On
ProxyPass / http://localhost:20211/
ProxyPassReverse / http://localhost:20211/
@@ -202,22 +206,22 @@
3. Activate the new website by running the following command:
`a2ensite pialert` or `service apache2 reload`
`a2ensite netalertx` or `service apache2 reload`
4. Once Apache restarts, you should be able to access the proxy website at http://pi.alert/
4. Once Apache restarts, you should be able to access the proxy website at http://netalertx/
<br>
## Apache HTTP Configuration (Sub Path)
1. On your Apache server, create a new file called /etc/apache2/sites-available/pialert.conf.
1. On your Apache server, create a new file called /etc/apache2/sites-available/netalertx.conf.
2. In this file, paste the following code:
```
<VirtualHost *:80>
ServerName pi.alert
location ^~ /pi.alert/ {
ServerName netalertx
location ^~ /netalertx/ {
ProxyPreserveHost On
ProxyPass / http://localhost:20211/
ProxyPassReverse / http://localhost:20211/
@@ -227,24 +231,24 @@
3. Activate the new website by running the following command:
`a2ensite pialert` or `service apache2 reload`
`a2ensite netalertx` or `service apache2 reload`
4. Once Apache restarts, you should be able to access the proxy website at http://pi.alert/
4. Once Apache restarts, you should be able to access the proxy website at http://netalertx/
<br>
## Apache HTTPS Configuration (Direct Path)
1. On your Apache server, create a new file called /etc/apache2/sites-available/pialert.conf.
1. On your Apache server, create a new file called /etc/apache2/sites-available/netalertx.conf.
2. In this file, paste the following code:
```
<VirtualHost *:443>
ServerName pi.alert
ServerName netalertx
SSLEngine On
SSLCertificateFile /etc/ssl/certs/pi.alert.pem
SSLCertificateKeyFile /etc/ssl/private/pi.alert.key
SSLCertificateFile /etc/ssl/certs/netalertx.pem
SSLCertificateKeyFile /etc/ssl/private/netalertx.key
ProxyPreserveHost On
ProxyPass / http://localhost:20211/
ProxyPassReverse / http://localhost:20211/
@@ -253,25 +257,25 @@
3. Activate the new website by running the following command:
`a2ensite pialert` or `service apache2 reload`
`a2ensite netalertx` or `service apache2 reload`
4. Once Apache restarts, you should be able to access the proxy website at https://pi.alert/
4. Once Apache restarts, you should be able to access the proxy website at https://netalertx/
<br>
## Apache HTTPS Configuration (Sub Path)
1. On your Apache server, create a new file called /etc/apache2/sites-available/pialert.conf.
1. On your Apache server, create a new file called /etc/apache2/sites-available/netalertx.conf.
2. In this file, paste the following code:
```
<VirtualHost *:443>
ServerName pi.alert
ServerName netalertx
SSLEngine On
SSLCertificateFile /etc/ssl/certs/pi.alert.pem
SSLCertificateKeyFile /etc/ssl/private/pi.alert.key
location ^~ /pi.alert/ {
SSLCertificateFile /etc/ssl/certs/netalertx.pem
SSLCertificateKeyFile /etc/ssl/private/netalertx.key
location ^~ /netalertx/ {
ProxyPreserveHost On
ProxyPass / http://localhost:20211/
ProxyPassReverse / http://localhost:20211/
@@ -281,9 +285,9 @@
3. Activate the new website by running the following command:
`a2ensite pialert` or `service apache2 reload`
`a2ensite netalertx` or `service apache2 reload`
4. Once Apache restarts, you should be able to access the proxy website at https://pi.alert/pi.alert/
4. Once Apache restarts, you should be able to access the proxy website at https://netalertx/netalertx/
## Reverse proxy example by using LinuxServer's SWAG container.
@@ -291,20 +295,20 @@
## [linuxserver/swag](https://github.com/linuxserver/docker-swag)
In the SWAG container create `/config/nginx/proxy-confs/pialert.subfolder.conf` with the following contents:
In the SWAG container create `/config/nginx/proxy-confs/netalertx.subfolder.conf` with the following contents:
``` nginx
## Version 2023/02/05
# make sure that your pialert container is named pialert
# pialert does not require a base url setting
# make sure that your netalertx container is named netalertx
# netalertx does not require a base url setting
# Since Pi.Alert uses a Host network, you may need to use the IP address of the system running Pi.Alert for $upstream_app.
# Since NetAlertX uses a Host network, you may need to use the IP address of the system running NetAlertX for $upstream_app.
location /pialert {
return 301 $scheme://$host/pialert/;
location /netalertx {
return 301 $scheme://$host/netalertx/;
}
location ^~ /pialert/ {
location ^~ /netalertx/ {
# enable the next two lines for http auth
#auth_basic "Restricted";
#auth_basic_user_file /config/nginx/.htpasswd;
@@ -321,44 +325,44 @@ location ^~ /pialert/ {
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app pialert;
set $upstream_app netalertx;
set $upstream_port 20211;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
proxy_set_header Accept-Encoding "";
proxy_redirect ~^/(.*)$ /pialert/$1;
rewrite ^/pialert/?(.*)$ /$1 break;
proxy_redirect ~^/(.*)$ /netalertx/$1;
rewrite ^/netalertx/?(.*)$ /$1 break;
sub_filter_once off;
sub_filter_types *;
sub_filter 'href="/' 'href="/pialert/';
sub_filter 'href="/' 'href="/netalertx/';
sub_filter '(?>$host)/css' '/pialert/css';
sub_filter '(?>$host)/js' '/pialert/js';
sub_filter '(?>$host)/css' '/netalertx/css';
sub_filter '(?>$host)/js' '/netalertx/js';
sub_filter '/img' '/pialert/img';
sub_filter '/lib' '/pialert/lib';
sub_filter '/php' '/pialert/php';
sub_filter '/img' '/netalertx/img';
sub_filter '/lib' '/netalertx/lib';
sub_filter '/php' '/netalertx/php';
}
```
## Traefik
> Submitted by [Isegrimm](https://github.com/Isegrimm) 🙏 (based on this [discussion](https://github.com/jokob-sk/Pi.Alert/discussions/449#discussioncomment-7281442))
> Submitted by [Isegrimm](https://github.com/Isegrimm) 🙏 (based on this [discussion](https://github.com/jokob-sk/NetAlertX/discussions/449#discussioncomment-7281442))
Asuming the user already has a working Traefik setup, this is what's needed to make Pi.Alert work at a URL like www.domain.com/pialert/.
Asuming the user already has a working Traefik setup, this is what's needed to make NetAlertX work at a URL like www.domain.com/netalertx/.
Note: Everything in these configs assumes '**www.domain.com**' as your domainname and '**section31**' as an arbitrary name for your certificate setup. You will have to substitute these with your own.
Also, I use the prefix '**pialert**'. If you want to use another prefix, change it in these files: dynamic.toml and default.
Also, I use the prefix '**netalertx**'. If you want to use another prefix, change it in these files: dynamic.toml and default.
Content of my yaml-file (this is the generic Traefik config, which defines which ports to listen on, redirect http to https and sets up the certificate process).
It also contains Authelia, which I use for authentication.
This part contains nothing specific to Pi.Alert.
This part contains nothing specific to NetAlertX.
```yaml
version: '3.8'
@@ -402,29 +406,29 @@ services:
restart: u
nless-stopped
```
Snippet of the dynamic.toml file (referenced in the yml-file above) that defines the config for Pi.Alert:
Snippet of the dynamic.toml file (referenced in the yml-file above) that defines the config for NetAlertX:
The following are self-defined keywords, everything else is traefik keywords:
- pialert-router
- pialert-service
- netalertx-router
- netalertx-service
- auth
- pialert-stripprefix
- netalertx-stripprefix
```toml
[http.routers]
[http.routers.pialert-router]
[http.routers.netalertx-router]
entryPoints = ["websecure"]
rule = "Host(`www.domain.com`) && PathPrefix(`/pialert`)"
service = "pialert-service"
middlewares = "auth,pialert-stripprefix"
[http.routers.pialert-router.tls]
rule = "Host(`www.domain.com`) && PathPrefix(`/netalertx`)"
service = "netalertx-service"
middlewares = "auth,netalertx-stripprefix"
[http.routers.netalertx-router.tls]
certResolver = "section31"
[[http.routers.pialert-router.tls.domains]]
[[http.routers.netalertx-router.tls.domains]]
main = "www.domain.com"
[http.services]
[http.services.pialert-service]
[[http.services.pialert-service.loadBalancer.servers]]
[http.services.netalertx-service]
[[http.services.netalertx-service.loadBalancer.servers]]
url = "http://internal-ip-address:20211/"
[http.middlewares]
@@ -432,12 +436,12 @@ The following are self-defined keywords, everything else is traefik keywords:
address = "http://authelia:9091/api/verify?rd=https://www.domain.com/authelia/"
trustForwardHeader = true
authResponseHeaders = ["Remote-User", "Remote-Groups", "Remote-Name", "Remote-Email"]
[http.middlewares.pialert-stripprefix.stripprefix]
prefixes = "/pialert"
[http.middlewares.netalertx-stripprefix.stripprefix]
prefixes = "/netalertx"
forceSlash = false
```
To make Pi.Alert work with this setup I modified the default file at `/etc/nginx/sites-available/default` in the docker container by copying it to my local filesystem, adding the changes as specified by [cvc90](https://github.com/cvc90) and mounting the new file into the docker container, overwriting the original one. By mapping the file instead of changing the file in-place, the changes persist if an updated dockerimage is pulled. This is also a downside when the default file is updated, so I only use this as a temporary solution, until the dockerimage is updated with this change.
To make NetAlertX work with this setup I modified the default file at `/etc/nginx/sites-available/default` in the docker container by copying it to my local filesystem, adding the changes as specified by [cvc90](https://github.com/cvc90) and mounting the new file into the docker container, overwriting the original one. By mapping the file instead of changing the file in-place, the changes persist if an updated dockerimage is pulled. This is also a downside when the default file is updated, so I only use this as a temporary solution, until the dockerimage is updated with this change.
Default-file:
@@ -446,9 +450,9 @@ server {
listen 80 default_server;
root /var/www/html;
index index.php;
#rewrite /pialert/(.*) / permanent;
add_header X-Forwarded-Prefix "/pialert" always;
proxy_set_header X-Forwarded-Prefix "/pialert";
#rewrite /netalertx/(.*) / permanent;
add_header X-Forwarded-Prefix "/netalertx" always;
proxy_set_header X-Forwarded-Prefix "/netalertx";
location ~* \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
@@ -462,18 +466,18 @@ server {
}
```
Mapping the updated file (on the local filesystem at `/appl/docker/pialert/default`) into the docker container:
Mapping the updated file (on the local filesystem at `/appl/docker/netalertx/default`) into the docker container:
```bash
docker run -d --rm --network=host \
--name=pi.alert \
-v /appl/docker/pialert/config:/home/pi/pialert/config \
-v /appl/docker/pialert/db:/home/pi/pialert/db \
-v /appl/docker/pialert/default:/etc/nginx/sites-available/default \
--name=netalertx \
-v /appl/docker/netalertx/config:/app/config \
-v /appl/docker/netalertx/db:/app/db \
-v /appl/docker/netalertx/default:/etc/nginx/sites-available/default \
-e TZ=Europe/Amsterdam \
-e PORT=20211 \
jokobsk/pi.alert:latest
jokobsk/netalertx:latest
```

View File

@@ -2,15 +2,15 @@
This is an explanation how settings are handled intended for anyone thinking about writing their own plugin or contributing to the project.
If you are a user of the app, settings should be described in the `Settings` section of the app. Open an issue if you'd like to clarify any of the settings.
If you are a user of the app, settings have a detailed description in the _Settings_ section of the app. Open an issue if you'd like to clarify any of the settings.
### 🛢 Data storage
The source of truth for user-defined values is the `pialert.conf` file. Editing the file makes the App overwrite values in the `Settings` database table and in the `table_settings.json` file.
The source of truth for user-defined values is the `app.conf` file. Editing the file makes the App overwrite values in the `Settings` database table and in the `table_settings.json` file.
#### 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 `pialert.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](/docs/DATABASE.md).
#### table_settings.json
@@ -20,27 +20,27 @@ This is the [API endpoint](/docs/API.md) that reflects the state of the `Setting
The json file is also cached on the client-side local storage of the browser.
#### pialert.conf
#### app.conf
> [!NOTE]
> This is the source of truth for settings. User-defined values in this files always override default values specified in the Plugin definition.
The App generates two `pialert.conf` entries for every setting (Since version 23.8+). One entry is the setting value, the second is the `__metadata` associated with the setting. This `__metadata` entry contains the full setting definition in JSON format. Currently unused, but intended to be used in future to extend the Settings system.
The App generates two `app.conf` entries for every setting (Since version 23.8+). One entry is the setting value, the second is the `__metadata` associated with the setting. This `__metadata` entry contains the full setting definition in JSON format. Currently unused, but intended to be used in future to extend the Settings system.
#### Plugin settings
> [!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 `pialert.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/Pi.Alert/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/front/plugins/README.md#-setting-object-structure), section `⚙ Setting object structure` for details on the structure of the setting.
![Screen 1][screen1]
### Settings Process flow
The process flow is mostly managed by the [initialise.py](/pialert/initialise.py) file.
The process flow is mostly managed by the [initialise.py](/server/initialise.py) file.
The script is responsible for reading user-defined values from a configuration file (`pialert.conf`), initializing settings, and importing them into a database. It also handles plugins and their configurations.
The script is responsible for reading user-defined values from a configuration file (`app.conf`), initializing settings, and importing them into a database. It also handles plugins and their configurations.
Here's a high-level description of the code:
@@ -49,7 +49,7 @@ Here's a high-level description of the code:
- `importConfigs`: This function is the main entry point of the script. It imports user settings from a configuration file, processes them, and saves them to the database.
- `read_config_file`: This function reads the configuration file (`pialert.conf`) and returns a dictionary containing the key-value pairs from the file.
- `read_config_file`: This function reads the configuration file (`app.conf`) and returns a dictionary containing the key-value pairs from the file.
2. Importing Configuration and Initializing Settings:
- The `importConfigs` function starts by checking the modification time of the configuration file to determine if it needs to be re-imported. If the file has not been modified since the last import, the function skips the import process.
@@ -74,4 +74,4 @@ Here's a high-level description of the code:
_____________________
[screen1]: https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/plugins_json_settings.png "Screen 1"
[screen1]: https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/plugins_json_settings.png "Screen 1"

View File

@@ -6,10 +6,10 @@
2. Under Security Options enable 2FA (Two-factor authentication)
3. Under Security Options generate an Application-specific password
4. Home -> Email Settings -> POP3 & IMAP -> Enable access to this account via POP3 and IMAP
5. In PiAlert specify these settings:
5. In NetAlertX specify these settings:
```python
REPORT_MAIL=True
SMTP_RUN='on_notification'
SMTP_SERVER='mail.gmx.com'
SMTP_PORT=465
SMTP_USER='gmx_email@gmx.com'
@@ -17,8 +17,8 @@
SMTP_SKIP_TLS=True
SMTP_FORCE_SSL=True
SMTP_SKIP_LOGIN=False
REPORT_FROM='gmx_email@gmx.com' # this has to be the same email as in SMTP_USER
REPORT_TO='some_target_email@gmail.com'
SMTP_REPORT_FROM='gmx_email@gmx.com' # this has to be the same email as in SMTP_USER
SMTP_REPORT_TO='some_target_email@gmail.com'
```
@@ -30,12 +30,12 @@
2. Specify the following settings:
```python
REPORT_MAIL=True
SMTP_RUN='on_notification'
SMTP_SKIP_TLS=True
SMTP_FORCE_SSL=True
SMTP_PORT=465
SMTP_SERVER='smtp.gmail.com'
SMTP_PASS='16-digit passcode from google'
REPORT_TO='some_target_email@gmail.com'
SMTP_REPORT_TO='some_target_email@gmail.com'
```

View File

@@ -2,16 +2,20 @@
You need to specify the network interface and the network mask. You can also configure multiple subnets and specify VLANS (see exceptions below).
> [!TIP]
> You may need to increase the time between scans `ARPSCAN_RUN_SCHD` and the timeout `ARPSCAN_RUN_TIMEOUT` settings when adding more subnets. If the timeout setting is exceeded, the scan is cancelled to prevent application hanging from rogue plugins. Check [debugging plugins](/docs/DEBUG_PLUGINS.md) for more tips.
## Examples
> [!NOTE]
> Please use the UI to configure settings as that ensures that the config file is in the correct format. Edit `pialert.conf` directly only when really necessary.
> Please use the UI to configure settings as that ensures that the config file is in the correct format. Edit `app.conf` directly only when really necessary.
> ![settings](/front/plugins/arp_scan/arp-scan-settings.png)
* Examples for one and two subnets (❗ Note the `['...', '...']` format):
* 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']`
## Explanation
### Network mask
@@ -31,21 +35,24 @@ 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))
> 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`).
![Network hardware](/docs/img/SUBNETS/system_info-network_hardware.png)
> [!TIP]
> Alterantive 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`).
### VLANs
**Example value: `-vlan=107`**
- Append e.g.: ` -vlan=107` to the interface field (e.g.: `eth0 -vlan=107`) for multiple vlans. More details in this [comment in this issue](https://github.com/jokob-sk/Pi.Alert/issues/170#issuecomment-1419902988)
- Append e.g.: ` -vlan=107` to the interface field (e.g.: `eth0 -vlan=107`) for multiple vlans. More details in this [comment in this issue](https://github.com/jokob-sk/NetAlertX/issues/170#issuecomment-1419902988)
#### VLANs on a Hyper-V setup
> Community sourced content by [mscreations](https://github.com/mscreations) from this [discussion](https://github.com/jokob-sk/Pi.Alert/discussions/404).
> Community sourced content by [mscreations](https://github.com/mscreations) from this [discussion](https://github.com/jokob-sk/NetAlertX/discussions/404).
> [!NOTE]
> The setup this was tested on: Bare Metal -> Hyper-V on Win Server 2019 -> Ubuntu 22.04 VM -> Docker -> PiAlert.
> The setup this was tested on: Bare Metal -> Hyper-V on Win Server 2019 -> Ubuntu 22.04 VM -> Docker -> NetAlertX.
**Approach 1 (may cause issues):**
@@ -84,8 +91,8 @@ network:
via: 192.168.1.1
```
3) Run `sudo netplan apply` and the interfaces are then available to scan in PiAlert.
4) In this case, use `192.168.2.0/24 --interface=eth0.2` in PiAlert
3) Run `sudo netplan apply` and the interfaces are then available to scan in NetAlertX.
4) In this case, use `192.168.2.0/24 --interface=eth0.2` in NetAlertX
#### VLAN 🔍Example:
@@ -95,6 +102,6 @@ network:
Please note the accessibility of the macvlans when they are configured on the same computer. My understanding this is a general networking behavior, but feel free to clarify via a PR/issue.
- Pi.Alert does not detect the macvlan container when it is running on the same computer.
- Pi.Alert recognizes the macvlan container when it is running on a different computer.
- NetAlertX does not detect the macvlan container when it is running on the same computer.
- NetAlertX recognizes the macvlan container when it is running on a different computer.

View File

@@ -1,6 +1,6 @@
## Am I running the latest released version?
Since version 23.01.14 PiAlert uses a simple timestamp-based version check to verify if a new version is available. You can check the [current and past releases here](https://github.com/jokob-sk/Pi.Alert/releases), or have a look at what I'm [currently working on](https://github.com/jokob-sk/Pi.Alert/issues/138).
Since version 23.01.14 NetAlertX uses a simple timestamp-based version check to verify if a new version is available. You can check the [current and past releases here](https://github.com/jokob-sk/NetAlertX/releases), or have a look at what I'm [currently working on](https://github.com/jokob-sk/NetAlertX/issues/138).
If you are not on the latest version, the app will notify you, that a new released version is avialable the following way:
@@ -22,4 +22,4 @@ For a comparison, this is how the UI looks like if you are on the latest stable
## Implementation details
During build a [/home/pi/pialert/front/buildtimestamp.txt](https://github.com/jokob-sk/Pi.Alert/blob/092797e75ccfa8359444ad149e727358ac4da05f/Dockerfile#L44) file is created. The app then periodically checks if a new release is available with a newer timestamp in GitHub's rest-based JSON endpoint (check the `def isNewVersion():` method in `pialert.py` for details).
During build a [/app/front/buildtimestamp.txt](https://github.com/jokob-sk/NetAlertX/blob/092797e75ccfa8359444ad149e727358ac4da05f/Dockerfile#L44) file is created. The app then periodically checks if a new release is available with a newer timestamp in GitHub's rest-based JSON endpoint (check the `def isNewVersion():` method for details).

View File

@@ -14,7 +14,7 @@
| v2.50 | First public release |
# 🆕 2022+ [Newest Release notes](https://github.com/jokob-sk/Pi.Alert/issues/138)
# 🆕 2022+ [Newest Release notes](https://github.com/jokob-sk/NetAlertX/issues/138)
## Pi.Alert v3.02
<!--- --------------------------------------------------------------------- --->
@@ -79,9 +79,9 @@
### Contact
Always use the Issue tracker for the correct fork, for example:
[jokob-sk/Pi.Alert](https://github.com/jokob-sk/Pi.Alert/issues). Please also follow the guidelines on:
[jokob-sk/NetAlertX](https://github.com/jokob-sk/NetAlertX/issues). Please also follow the guidelines on:
- [Pull Request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-pull-requests-prs)
- 🙏 [Feature request guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-feature-requests)
- 🐛 [Issue guidelines](https://github.com/jokob-sk/Pi.Alert/tree/main/docs#-submitting-an-issue-or-bug)
- [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)

View File

@@ -1,9 +1,11 @@
### Create a simple n8n workflow
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)
### Specify your email template
See [sample JSON](https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json) if you want to see the JSON paths used in the email template below
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)
```
@@ -14,5 +16,5 @@ 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)
### Configure PiAlert to point to the above URL
![PiAlert config](/docs/img/WEBHOOK_N8N/Webhook_settings.png)
### Configure NetAlertX to point to the above URL
![NetAlertX config](/docs/img/WEBHOOK_N8N/Webhook_settings.png)

View File

@@ -2,7 +2,7 @@
## How does the signing work?
Pi.Alert will use the configured secret to create a hash signature of the request body. This SHA256-HMAC signature will appear in the `X-Webhook-Signature` header of each request to the webhook target URL. You can use the value of this header to validate the request was sent by Pi.Alert.
NetAlertX will use the configured secret to create a hash signature of the request body. This SHA256-HMAC signature will appear in the `X-Webhook-Signature` header of each request to the webhook target URL. You can use the value of this header to validate the request was sent by NetAlertX.
## Activating webhook signatures
@@ -12,7 +12,7 @@ All you need to do in order to add a signature to the request headers is to set
There are a few things to keep in mind when validating the webhook delivery:
- Pi.Alert uses an HMAC hex digest to compute the hash
- NetAlertX uses an HMAC hex digest to compute the hash
- The signature in the `X-Webhook-Signature` header always starts with `sha256=`
- The hash signature is generated using the configured `WEBHOOK_SECRET` and the request body.
- Never use a plain `==` operator. Instead, consider using a method like [`secure_compare`](https://www.rubydoc.info/gems/rack/Rack%2FUtils:secure_compare) or [`crypto.timingSafeEqual`](https://nodejs.org/api/crypto.html#cryptotimingsafeequala-b), which performs a "constant time" string comparison to help mitigate certain timing attacks against regular equality operators, or regular loops in JIT-optimized languages.

View File

@@ -3,7 +3,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/Pi.Alert/blob/main/docs/DEBUG_TIPS.md)
1. [Follow steps 1, 2, 3, 4 on this page](https://github.com/jokob-sk/NetAlertX/blob/main/docs/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 apt-get install lsof`
1. `sudo lsof -i`

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
docs/img/ICONS/paste-svg.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -1,8 +1,8 @@
/* -----------------------------------------------------------------------------
# Pi.Alert
# NetAlertX
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert.css - Front module. CSS styles
# app.css - Front module. CSS styles
#-------------------------------------------------------------------------------
# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3
----------------------------------------------------------------------------- */
@@ -151,10 +151,26 @@
/* -----------------------------------------------------------------------------
Customized Main Menu
----------------------------------------------------------------------------- */
.NetAlertX-logo
{
border-color:transparent !important;
height: 50px !important;
width: 50px !important;
margin-top:15px !important;
border-radius: 1px !important;
}
.main-header .logo {
width: 150px;
}
.navbar-nav > .user-menu .user-image
{
margin-top: 3px;
}
.main-header>.navbar {
margin-left: 150px;
}
@@ -487,6 +503,73 @@
display: none;
}
/* ticker setup */
.ticker-li
{
width: 40%;
}
#ticker_announcement_plc
{
/* height: 50px; */
overflow: hidden;
width: 65%;
position: absolute;
left: 40px;
top: 15px;
}
@media (max-width: 1500px) and (min-width: 1101px) {
#ticker_announcement_plc {
width: 45%; /* Width for screen sizes between 1100px and 730px */
}
}
@media (max-width: 1100px) and (min-width: 801px) {
#ticker_announcement_plc {
width: 30%; /* Width for screen sizes between 1100px and 730px */
}
}
@media (max-width: 800px) {
#ticker_announcement_plc {
width: 25%; /* Width for screen sizes less than 730px */
}
}
#ticker-message a
{
color:#3200bb;
text-decoration: underline;
}
#ticker-message
{
color:#FFFFFF;
}
#ticker_announcement_plc:hover .ticker_announcement {
animation-play-state: paused;
}
@keyframes marquee {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-150%);
}
}
.ticker_announcement {
text-align: center;
white-space: nowrap;
animation: marquee 20s linear infinite;
cursor: default;
}
/* maintenance buttons */
.dbtools-button {
display: inline-block;
@@ -792,9 +875,13 @@ input[readonly] {
cursor: not-allowed;
}
/* Devices */
/* ----------------------------------------------------------------- */
/* Devices page */
/* ----------------------------------------------------------------- */
#txtIconFA {
min-width: 18px;
min-width: 40px;
}
@@ -846,7 +933,24 @@ input[readonly] {
margin-bottom: 6px;
}
#tableDevicesBox td svg, #tableDevicesBox td i{
height: 1.5em !important;
}
#dropdownIcon li svg, #dropdownIcon li i{
height: 1.5em !important;
}
#modal-input-textarea
{
width: 100%;
}
/* ----------------------------------------------------------------- */
/* NETWORK page */
/* ----------------------------------------------------------------- */
/* AdminLTE overrides */
#networkTree .box
@@ -890,11 +994,18 @@ input[readonly] {
}
#networkTree .netIcon
{
width: 25px;;
width: 25px;
float:left;
display:inline;
text-align: center;
}
#networkTree .netIcon svg
{
height: 1.2em;
width: auto;
}
#networkTree .netCollapse
{
display: block;
@@ -921,6 +1032,31 @@ input[readonly] {
text-overflow: ellipsis;
}
.networkTable .nav-tabs li i, .networkTable .nav-tabs li svg {
padding: 3px;
height: 2em !important;
/* width: 2em !important; */
position: absolute;
/* z-index: 10; */
top: 0.3em;
/* margin-left: 0.2em; */
}
.networkTable .icon {
/* padding-left:2em; */
width:2em;
height:2em;
float: left;
/* background-color:red; */
}
/* ----------------------------------------------------------------- */
/* PLUGINS page */
/* ----------------------------------------------------------------- */
.plugin-filters
{
margin: 7px;
@@ -993,6 +1129,7 @@ input[readonly] {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: white;
}
@@ -1030,6 +1167,53 @@ input[readonly] {
z-index: 100;
}
/* Multi-edit adjustements */
.box-header
{
min-height: 55px;
}
.red-hover-border:hover
{
border-color: red !important;
border-width: 1px;
border-style: solid;
}
.red-hover-background:hover
{
background-color: red !important;
}
#multi-edit-form .form-group
{
height: 45px;
}
.pia-top-left-logo
{
height:50px;
}
/* -----------------------------------------------------------------------------
Floating edit button
----------------------------------------------------------------------------- */
#multiEditPlc
{
position: fixed;
bottom: 50px;
right: 0px;
z-index: 10;
}
table.dataTable tbody > tr.selected
{
color:red;
}
/* -----------------------------------------------------------------------------
Donations
----------------------------------------------------------------------------- */

View File

@@ -725,4 +725,6 @@ input[type="password"]::-webkit-caps-lock-indicator {
}
.pa_semitransparent-panel{
background-color: #000 !important;
}
}

View File

@@ -1,6 +1,6 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# deviceDetails.php - Front module. Device management page #
@@ -164,6 +164,7 @@
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="fa fa-caret-down "></span></button>
<ul id="dropdownOwner" class="dropdown-menu dropdown-menu-right">
<li id="dropdownOwner_tmp"></li>
</ul>
</div>
</div>
@@ -181,7 +182,7 @@
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false" >
<span class="fa fa-caret-down"></span></button>
<ul id="dropdownDeviceType" class="dropdown-menu dropdown-menu-right">
<li id="dropdownDeviceType_tmp"></li>
</ul>
</div>
</div>
@@ -189,21 +190,23 @@
</div>
<!-- Icon -->
<div class="form-group" title="<?= lang('DevDetail_Icon_Descr');?>">
<div class="form-group" >
<label class="col-sm-3 control-label">
<?= lang('DevDetail_Icon');?>
<a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/ICONS.md" target="_blank"> <span><i class="fa fa-circle-question"></i></a><span>
<a href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/ICONS.md" target="_blank"> <span><i class="fa fa-circle-question"></i></a><span>
</label>
<div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa" id="txtIconFA" onclick="editDrp('txtIcon');"></i></span>
<input class="form-control" id="txtIcon" type="text" value="--">
<span class="input-group-addon" id="txtIconFA"></span>
<input class="form-control" id="txtIcon" type="text" value="--" readonly>
<span class="input-group-addon" title='<?= lang('DevDetail_button_AddIcon_Tooltip');?>'><i class="fa fa-square-plus pointer" onclick="askAddIcon();"></i></span>
<span class="input-group-addon" title='<?= lang('DevDetail_button_OverwriteIcons_Tooltip');?>'><i class="fa fa-copy pointer" onclick="askOverwriteIconType();"></i></span>
<div class="input-group-btn">
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false" >
<span class="fa fa-caret-down"></span>
</button>
<ul id="dropdownIcon" class="dropdown-menu dropdown-menu-right">
<ul id="dropdownIcon" class="dropdown-menu dropdown-menu-right" >
<li id="dropdownIcon_tmp"></li>
</ul>
</div>
</div>
@@ -238,6 +241,7 @@
<span class="fa fa-caret-down"></span>
</button>
<ul id="dropdownGroup" class="dropdown-menu dropdown-menu-right">
<li id="dropdownGroup_tmp"></li>
</ul>
</div>
</div>
@@ -255,7 +259,7 @@
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="fa fa-caret-down"></span></button>
<ul id="dropdownLocation" class="dropdown-menu dropdown-menu-right">
<li id="dropdownLocation_tmp"></li>
</ul>
</div>
</div>
@@ -321,7 +325,7 @@
</div>
<!-- Network -->
<h4 class="bottom-border-aqua"><?= lang('DevDetail_MainInfo_Network_Title');?><span class="networkPageHelp"> <a target="_blank" href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/NETWORK_TREE.md"><i class="fa fa-circle-question"></i></a><span></h4>
<h4 class="bottom-border-aqua"><?= lang('DevDetail_MainInfo_Network_Title');?><span class="networkPageHelp"> <a target="_blank" href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md"><i class="fa fa-circle-question"></i></a><span></h4>
<div class="form-group" title="<?= lang('DevDetail_Network_Node_hover');?>">
<label class="col-sm-3 control-label"><?= lang('DevDetail_MainInfo_Network');?></label>
<div class="col-sm-9">
@@ -333,6 +337,7 @@
<button type="button" class="btn btn-info dropdown-toggle" data-mynodemac="" data-toggle="dropdown" aria-expanded="false" id="buttonNetworkNodeMac">
<span class="fa fa-caret-down"></span></button>
<ul id="dropdownNetworkNodeMac" class="dropdown-menu dropdown-menu-right">
<li id="dropdownNetworkNodeMac_tmp"></li>
</ul>
</div>
@@ -437,7 +442,7 @@
<span id="iconRandomMACactive" data-toggle="tooltip" data-placement="right" title="Random MAC is Active" class="hidden">
<i style="font-size: 24px;" class="text-yellow glyphicon glyphicon-random"></i> &nbsp &nbsp </span>
<a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/RANDOM_MAC.md" target="_blank" style="color: #777;">
<a href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/RANDOM_MAC.md" target="_blank" style="color: #777;">
<i class="fa fa-info-circle"></i> </a>
</div>
</div>
@@ -621,6 +626,10 @@
<script src="lib/AdminLTE/bower_components/moment/moment.js"></script>
<script src="lib/AdminLTE/bower_components/fullcalendar/dist/fullcalendar.min.js"></script>
<script src="lib/AdminLTE/bower_components/fullcalendar/dist/locale-all.js"></script>
<!-- ----------------------------------------------------------------------- -->
<script src="js/ui_components.js"></script>
<script src="js/db_methods.js"></script>
<!-- ----------------------------------------------------------------------- -->
<!-- Dark-Mode Patch -->
<?php
@@ -632,14 +641,6 @@ if ($ENABLED_DARKMODE === True) {
<!-- page script ----------------------------------------------------------- -->
<script defer>
// ------------------------------------------------------------
function getMac(){
params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
return params.mac
}
// ------------------------------------------------------------
function getDevicesList()
@@ -653,6 +654,26 @@ if ($ENABLED_DARKMODE === True) {
devicesList = [];
}
// only loop thru the filtered down list
visibleDevices = getCache("ntx_visible_macs")
if(visibleDevices != "") {
visibleDevicesMACs = visibleDevices.split(',');
devicesList_tmp = [];
// Iterate through the data and filter only visible devices
$.each(devicesList, function(index, item) {
// Check if the current item's MAC exists in visibleDevicesMACs
if (visibleDevicesMACs.includes(item.dev_MAC)) {
devicesList_tmp.push(item);
}
});
// Update devicesList with the filtered items
devicesList = devicesList_tmp;
}
return devicesList;
}
@@ -661,7 +682,6 @@ if ($ENABLED_DARKMODE === True) {
mac = getMac() // can also be rowID!! not only mac
var devicesList = []; // this will contain a list the database row IDs of the devices ordered by the position displayed in the UI
main();
var pos = -1;
var parPeriod = 'Front_Details_Period';
@@ -678,6 +698,7 @@ if ($ENABLED_DARKMODE === True) {
var selectedTab = 'tabDetails';
var emptyArr = ['undefined', "", undefined, null];
main();
// -----------------------------------------------------------------------------
@@ -701,67 +722,37 @@ function main () {
tab = selectedTab;
// get parameter value
$.get('php/server/parameters.php?action=get&defaultValue=1 day&parameter='+ parPeriod, function(data) {
var result = JSON.parse(data);
if (result) {
period = result;
$('#period').val(period);
period = '1 day';
sessionsRows = 50;
eventsRows = 50;
$('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
// Initialize components with parameters
initializeTabs();
initializeiCheck();
initializeCombos();
initializeDatatables();
initializeCalendar();
// query data
getDeviceData(true);
getSessionsPresenceEvents();
// Force re-render calendar on tab change
// (bugfix for render error at left panel)
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (nav) {
if ($(nav.target).attr('href') == '#panPresence') {
$('#calendar').fullCalendar('rerenderEvents');
}
// get parameter value
$.get('php/server/parameters.php?action=get&defaultValue=50&parameter='+ parSessionsRows, function(data) {
var result = JSON.parse(data);
if (Number.isInteger (result) ) {
sessionsRows = result;
}
// get parameter value
$.get('php/server/parameters.php?action=get&defaultValue=50&parameter='+ parEventsRows, function(data) {
var result = JSON.parse(data);
if (Number.isInteger (result) ) {
eventsRows = result;
}
// get parameter value
$.get('php/server/parameters.php?action=get&defaultValue=true&parameter='+ parEventsHide, function(data) {
var result = JSON.parse(data);
if (result) {
eventsHide = result;
$('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
}
// Initialize components with parameters
initializeTabs();
initializeiCheck();
initializeCombos();
initializeDatatables();
initializeCalendar();
// query data
getDeviceData(true);
getSessionsPresenceEvents();
// Force re-render calendar on tab change
// (bugfix for render error at left panel)
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (nav) {
if ($(nav.target).attr('href') == '#panPresence') {
$('#calendar').fullCalendar('rerenderEvents');
}
});
// Show device icon as it changes
$('#txtIcon').on('change input', function() {
$('#txtIconFA').removeClass().addClass(`fa fa-${$(this).val()} pointer`)
});
});
});
});
});
}
// Show device icon as it changes
$('#txtIcon').on('change input', function() {
updateIconPreview('#txtIcon')
});
}
// -----------------------------------------------------------------------------
@@ -820,15 +811,26 @@ function initializeiCheck () {
// -----------------------------------------------------------------------------
function initializeCombos () {
// Initialize combos with queries
initializeCombo ( '#dropdownOwner', 'getOwners', 'txtOwner', true);
initializeCombo ( '#dropdownDeviceType', 'getDeviceTypes', 'txtDeviceType', true);
initializeCombo ( '#dropdownGroup', 'getGroups', 'txtGroup', true);
initializeCombo ( '#dropdownLocation', 'getLocations', 'txtLocation', true);
initializeCombo ( '#dropdownNetworkNodeMac', 'getNetworkNodes', 'txtNetworkNodeMac', false);
initializeCombo ( '#dropdownIcon', 'getIcons', 'txtIcon', false);
initializeCombo ( '#dropdownAction', 'getActions', 'txtAction', false);
initializeCombo ( '#dropdownDevices', 'getDevices', 'txtFromDevice', false);
// Initiate dropdown
// function initSettingDropdown(settingKey, // Identifier for the setting
// valuesArray, // Array of values to be pre-selected in the dropdown
// targetLocation, // ID of the HTML element where dropdown should be rendered (will be replaced)
// callbackToGenerateEntries, // Callback function to generate entries based on options
// targetField, // Target field or element where selected value should be applied or updated
// nameTransformer) // callback to transform name
initSettingDropdown("NEWDEV_dev_Icon", [], "dropdownIcon_tmp", genListWithInputSet, 'txtIcon', atob )
initSettingDropdown("NEWDEV_dev_DeviceType", [], "dropdownDeviceType_tmp", genListWithInputSet, 'txtDeviceType' )
initSettingDropdown("NEWDEV_dev_Owner", [], "dropdownOwner_tmp", genListWithInputSet, 'txtOwner' )
initSettingDropdown("NEWDEV_dev_Group", [], "dropdownGroup_tmp", genListWithInputSet, 'txtGroup' )
initSettingDropdown("NEWDEV_dev_Location", [], "dropdownLocation_tmp", genListWithInputSet, 'txtLocation' )
initSettingDropdown("NEWDEV_dev_Network_Node_MAC_ADDR", [], "dropdownNetworkNodeMac_tmp", genListWithInputSet, 'txtNetworkNodeMac' )
// Initialize static combos
initializeComboSkipRepeated ();
}
@@ -843,7 +845,7 @@ function initializeCombo (dropdownId, queryAction, txtDataField, useCache) {
// get data from server
$.get('php/server/devices.php?action='+queryAction, function(data) {
console.log(data)
// console.log(data)
var listData = JSON.parse(data);
var order = 1;
@@ -904,9 +906,8 @@ function writeDropdownHtml(dropdownId, dropdownHtmlContent)
HTMLelement.innerHTML = ''
HTMLelement.innerHTML += dropdownHtmlContent;
}
// -----------------------------------------------------------------------------
function initializeComboSkipRepeated () {
// find dropdown menu element
HTMLelement = $('#dropdownSkipRepeated')[0];
@@ -1138,6 +1139,10 @@ function initializeCalendar () {
if (isLoading) {
showSpinner()
} else {
setTimeout(() => {
updateIconPreview('#txtIcon')
}, 100);
hideSpinner()
}
}
@@ -1288,19 +1293,29 @@ function getDeviceData (readAllData=false) {
devicesList = getDevicesList();
// handle empty dev_Network_Node_MAC_ADDR
networkParentMac = deviceData['dev_Network_Node_MAC_ADDR']
if(networkParentMac)
{
networkParentMacName = getDeviceDataByMacAddress(deviceData['dev_Network_Node_MAC_ADDR'], "dev_Name")
} else
{
networkParentMacName = '--'
}
$('#txtMAC').val (deviceData['dev_MAC']);
$('#txtName').val (deviceData['dev_Name']);
$('#txtOwner').val (deviceData['dev_Owner']);
$('#txtDeviceType').val (deviceData['dev_DeviceType']);
$('#txtVendor').val (deviceData['dev_Vendor']);
$('#txtIcon').val (initDefault(deviceData['dev_Icon'], 'laptop'));
$('#txtIcon').val (initDefault(deviceData['dev_Icon'], 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==')); // base64 laptop icon
$('#txtIcon').trigger('change')
if (deviceData['dev_Favorite'] == 1) {$('#chkFavorite').iCheck('check');} else {$('#chkFavorite').iCheck('uncheck');}
$('#txtGroup').val (deviceData['dev_Group']);
$('#txtLocation').val (deviceData['dev_Location']);
$('#txtComments').val (deviceData['dev_Comments']);
$('#txtNetworkNodeMac').val ( getDeviceDataByMacAddress(deviceData['dev_Network_Node_MAC_ADDR'], "dev_Name")) ;
$('#txtNetworkNodeMac').val ( networkParentMacName) ;
$('#txtNetworkNodeMac').attr ('data-mynodemac', deviceData['dev_Network_Node_MAC_ADDR']);
$('#txtNetworkPort').val (deviceData['dev_Network_Node_port']);
// disabling network node configuration if root Internet node
@@ -1432,7 +1447,7 @@ function setDeviceData (direction='', refreshCallback='') {
+ '&owner=' + $('#txtOwner').val()
+ '&type=' + $('#txtDeviceType').val()
+ '&vendor=' + $('#txtVendor').val()
+ '&icon=' + $('#txtIcon').val()
+ '&icon=' + encodeURIComponent($('#txtIcon').val())
+ '&favorite=' + ($('#chkFavorite')[0].checked * 1)
+ '&group=' + $('#txtGroup').val()
+ '&location=' + $('#txtLocation').val()
@@ -1471,23 +1486,7 @@ function setDeviceData (direction='', refreshCallback='') {
});
}
// --------------------------------------------------------
// Calls a backend function to add a front-end event to an execution queue
function updateApi()
{
// value has to be in format event|param. e.g. run|ARPSCAN
action = `update_api|devices,appevents`
$.ajax({
method: "POST",
url: "php/server/util.php",
data: { function: "addToExecutionQueue", action: action },
success: function(data, textStatus) {
console.log(data)
}
})
}
// -----------------------------------------------------------------------------
@@ -1618,7 +1617,7 @@ function overwriteIconType () {
return;
}
var icon = $('#txtIcon').val();
var icon = encodeURIComponent($('#txtIcon').val());
// Mass update icons
$.get('php/server/devices.php?action=overwriteIconType&mac='+ mac + '&icon=' + icon, function(msg) {
@@ -1629,6 +1628,42 @@ function overwriteIconType () {
$('#panDetails :input').attr('disabled', true);
}
// -----------------------------------------------------------------------------
// Add a new Icon
function askAddIcon () {
// Check MAC
if (mac == '') {
return;
}
// Add new icon as base64 string
showModalInput ('<i class="fa fa-square-plus pointer"></i> <?= lang('DevDetail_button_AddIcon');?>', '<?= lang('DevDetail_button_AddIcon_Help');?>',
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Okay');?>', 'addAsBase64');
}
// -----------------------------------------------------------------------------
function addAsBase64 () {
// Check MAC
if (mac == '') {
return;
}
var iconHtml = $('#modal-input-textarea').val();
console.log(iconHtml);
iconHtmlBase64 = btoa(iconHtml.replace(/"/g, "'"));
console.log(iconHtmlBase64);
$('#txtIcon').val(iconHtmlBase64);
updateIconPreview('#txtIcon')
}
// -----------------------------------------------------------------------------
function askDeleteDevice () {
// Check MAC

View File

@@ -1,6 +1,4 @@
<script>
deviceIP = getDeviceDataByMacAddress("<?php echo $_REQUEST["mac"]?>", "dev_LastIP")
</script>
<?php if ($_REQUEST["mac"] == "Internet") { ?>
@@ -79,16 +77,16 @@
<?= lang("DevDetail_Nmap_Scans_desc") ?>
</div>
<button type="button" id="piamanualnmap_fast" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(deviceIP, 'fast')">
<button type="button" id="piamanualnmap_fast" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(getDeviceDataByMacAddress(getMac(), 'dev_LastIP'), 'fast')">
<?= lang("DevDetail_Loading") ?>
</button>
<button type="button" id="piamanualnmap_normal" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(deviceIP, 'normal')">
<button type="button" id="piamanualnmap_normal" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(getDeviceDataByMacAddress(getMac(), 'dev_LastIP'), 'normal')">
<?= lang("DevDetail_Loading") ?>
</button>
<button type="button" id="piamanualnmap_detail" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(deviceIP, 'detail')">
<button type="button" id="piamanualnmap_detail" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(getDeviceDataByMacAddress(getMac(), 'dev_LastIP'), 'detail')">
<?= lang("DevDetail_Loading") ?>
</button>
<button type="button" id="piamanualnmap_skipdiscovery" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(deviceIP, 'skipdiscovery')">
<button type="button" id="piamanualnmap_skipdiscovery" class="btn btn-primary pa-btn" style="margin-bottom: 20px; margin-left: 10px; margin-right: 10px;" onclick="manualnmapscan(getDeviceDataByMacAddress(getMac(), 'dev_LastIP'), 'skipdiscovery')">
<?= lang("DevDetail_Loading") ?>
</button>
@@ -129,7 +127,7 @@
beforeSend: function() { $('#scanoutput').addClass("ajax_scripts_loading"); },
complete: function() { $('#scanoutput').removeClass("ajax_scripts_loading"); },
success: function(data, textStatus) {
console.log(data);
// console.log(data);
$("#scanoutput").html(data);
}
})
@@ -157,7 +155,7 @@
$( "#tracerouteoutput" ).empty();
$.ajax({
method: "GET",
url: "./php/server/traceroute.php?action=get&ip=" + deviceIP + "",
url: "./php/server/traceroute.php?action=get&ip=" + getDeviceDataByMacAddress(getMac(), 'dev_LastIP') + "",
beforeSend: function() { $('#tracerouteoutput').addClass("ajax_scripts_loading"); },
complete: function() { $('#tracerouteoutput').removeClass("ajax_scripts_loading"); },
success: function(data, textStatus) {
@@ -172,7 +170,7 @@
$( "#nslookupoutput" ).empty();
$.ajax({
method: "GET",
url: "./php/server/nslookup.php?action=get&ip=" + deviceIP + "",
url: "./php/server/nslookup.php?action=get&ip=" + getDeviceDataByMacAddress(getMac(), 'dev_LastIP') + "",
beforeSend: function() { $('#nslookupoutput').addClass("ajax_scripts_loading"); },
complete: function() { $('#nslookupoutput').removeClass("ajax_scripts_loading"); },
success: function(data, textStatus) {
@@ -182,20 +180,22 @@
}
// ----------------------------------------------------------------
setTimeout(function(){
document.getElementById('piamanualnmap_fast').innerHTML='<?= lang(
"DevDetail_Nmap_buttonFast"
) ?> (' + deviceIP +')';
document.getElementById('piamanualnmap_normal').innerHTML='<?= lang(
"DevDetail_Nmap_buttonDefault"
) ?> (' + deviceIP +')';
document.getElementById('piamanualnmap_detail').innerHTML='<?= lang(
"DevDetail_Nmap_buttonDetail"
) ?> (' + deviceIP +')';
document.getElementById('piamanualnmap_skipdiscovery').innerHTML='<?= lang(
"DevDetail_Nmap_buttonSkipDiscovery"
) ?> (' + deviceIP +')';
}, 2000);
function initNmapButtons() {
setTimeout(function(){
document.getElementById('piamanualnmap_fast').innerHTML=getString(
"DevDetail_Nmap_buttonFast"
) ;
document.getElementById('piamanualnmap_normal').innerHTML=getString(
"DevDetail_Nmap_buttonDefault"
) ;
document.getElementById('piamanualnmap_detail').innerHTML=getString(
"DevDetail_Nmap_buttonDetail"
) ;
document.getElementById('piamanualnmap_skipdiscovery').innerHTML=getString(
"DevDetail_Nmap_buttonSkipDiscovery"
) ;
}, 500);
}
// ----------------------------------------------------------------
@@ -211,4 +211,7 @@
}
})
}
// init first time
initNmapButtons();
</script>

View File

@@ -1,6 +1,6 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# devices.php - Front module. Devices list page #
@@ -19,12 +19,14 @@
// check permissions
$dbPath = "../db/pialert.db";
$confPath = "../config/pialert.conf";
$dbPath = "../db/app.db";
$confPath = "../config/app.conf";
checkPermissions([$dbPath, $confPath]);
?>
<script src="js/ui_components.js"></script>
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
@@ -39,8 +41,9 @@
<!-- Main content ---------------------------------------------------------- -->
<section class="content">
<!-- top small box 1 ------------------------------------------------------- -->
<div class="row">
<!-- Tile toggle cards ------------------------------------------------------- -->
<div class="row" id="TileCards">
<!-- top small box 1 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('my');">
<div class="small-box bg-aqua">
@@ -52,7 +55,7 @@
</a>
</div>
<!-- top small box 2 ------------------------------------------------------- -->
<!-- top small box 2 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('connected');">
<div class="small-box bg-green">
@@ -64,7 +67,7 @@
</a>
</div>
<!-- top small box 3 ------------------------------------------------------- -->
<!-- top small box 3 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('favorites');">
<div class="small-box bg-yellow">
@@ -76,7 +79,7 @@
</a>
</div>
<!-- top small box 4 ------------------------------------------------------- -->
<!-- top small box 4 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('new');">
<div class="small-box bg-yellow">
@@ -88,7 +91,7 @@
</a>
</div>
<!-- top small box 5 ------------------------------------------------------- -->
<!-- top small box 5 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('down');">
<div class="small-box bg-red">
@@ -100,7 +103,7 @@
</a>
</div>
<!-- top small box 6 ------------------------------------------------------- -->
<!-- top small box 6 ------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: initializeDatatable('archived');">
<div class="small-box bg-gray top_small_box_gray_text">
@@ -114,13 +117,13 @@
</div>
<!-- Activity Chart ------------------------------------------------------- -->
<!-- Device presence / Activity Chart ------------------------------------------------------- -->
<div class="row">
<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>
<h3 class="box-title"><?= lang('Device_Shortcut_OnlineChart');?> </h3>
</div>
<div class="box-body">
<div class="chart">
@@ -138,7 +141,15 @@
var pia_js_online_history_ondev = [<?php pia_graph_devices_data($Pia_Graph_Device_Online); ?>];
var pia_js_online_history_dodev = [<?php pia_graph_devices_data($Pia_Graph_Device_Down); ?>];
var pia_js_online_history_ardev = [<?php pia_graph_devices_data($Pia_Graph_Device_Arch); ?>];
pia_draw_graph_online_history(pia_js_online_history_time, pia_js_online_history_ondev, pia_js_online_history_dodev, pia_js_online_history_ardev);
setTimeout(() => {
pia_draw_graph_online_history(
pia_js_online_history_time,
pia_js_online_history_ondev,
pia_js_online_history_dodev,
pia_js_online_history_ardev);
}, 500);
</script>
<!-- datatable ------------------------------------------------------------- -->
@@ -148,7 +159,9 @@
<!-- box-header -->
<div class="box-header">
<h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3>
<div class=" col-md-10 ">
<h3 id="tableDevicesTitle" class="box-title text-gray "></h3>
</div>
</div>
<!-- table -->
@@ -173,6 +186,7 @@
<!-- ----------------------------------------------------------------------- -->
</section>
<!-- /.content -->
<div id="multiEditPlc" class="col-md-2"></div>
</div>
<!-- /.content-wrapper -->
@@ -186,9 +200,10 @@
<!-- ----------------------------------------------------------------------- -->
<!-- Datatable -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css">
<link rel="stylesheet" href="lib/AdminLTE/bower_components/datatables.net/css/select.dataTables.min.css">
<script src="lib/AdminLTE/bower_components/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="lib/AdminLTE/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
<script src="lib/AdminLTE/bower_components/datatables.net/js/dataTables.select.min.js"></script>
<!-- page script ----------------------------------------------------------- -->
<script>
@@ -226,6 +241,7 @@
];
// Read parameters & Initialize components
showSpinner();
main();
@@ -234,6 +250,9 @@ function main () {
handleLoadingDialog()
// Hide UI elements as per settings
hideUIelements("UI_DEV_SECTIONS")
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
cookieColumnsVisibleStr = decodeURI(getCookie("Front_Devices_Columns_Visible")).replaceAll('%2C',',')
@@ -291,11 +310,12 @@ function main () {
}
// Initialize components with parameters
initializeDatatable('my');
initializeDatatable(getUrlAnchor('my'));
// check if dat outdated and show spinner if so
// check if data outdated and show spinner if so
handleLoadingDialog()
@@ -348,7 +368,7 @@ function getDevicesTotals(devicesData) {
setCache("getDevicesTotals", resultJSON);
}
console.log(resultJSON);
// console.log(resultJSON);
}
// -----------------------------------------------------------------------------
@@ -359,19 +379,19 @@ function filterDataByStatus(data, status) {
case 'my':
to_display = getSetting('UI_MY_DEVICES');
let result = false;
let result = true;
if (to_display.includes('online') && item.dev_PresentLastScan === 1) {
result = true;
} else if (to_display.includes('offline') && item.dev_PresentLastScan === 0) {
result = true;
} else if (to_display.includes('archived') && item.dev_Archived === 1) {
result = true;
} else if (to_display.includes('new') && item.dev_NewDevice === 1) {
result = true;
} else if (to_display.includes('down') && item.dev_PresentLastScan === 0 && item.dev_AlertDeviceDown !== 0) {
result = true;
}
if (!to_display.includes('down') && item.dev_PresentLastScan === 0 && item.dev_AlertDeviceDown !== 0) {
result = false;
} else if (!to_display.includes('new') && item.dev_NewDevice === 1) {
result = false;
} else if (!to_display.includes('archived') && item.dev_Archived === 1) {
result = false;
} else if (!to_display.includes('offline') && item.dev_PresentLastScan === 0) {
result = false;
} else if (!to_display.includes('online') && item.dev_PresentLastScan === 1) {
result = false;
}
return result; // Include all items for 'my' status
case 'connected':
@@ -381,7 +401,9 @@ function filterDataByStatus(data, status) {
case 'new':
return item.dev_NewDevice === 1;
case 'down':
return item.dev_PresentLastScan === 0 && item.dev_AlertDeviceDown !== 0;
return (item.dev_PresentLastScan === 0 && item.dev_AlertDeviceDown !== 0) || item.dev_PresentLastScan === 0;
case 'down_only':
return (item.dev_PresentLastScan === 0 && item.dev_AlertDeviceDown !== 0);
case 'archived':
return item.dev_Archived === 1;
default:
@@ -421,6 +443,11 @@ function getDeviceStatus(item)
// -----------------------------------------------------------------------------
function initializeDatatable (status) {
if(!status)
{
status = 'my'
}
// Save status selected
deviceStatus = status;
@@ -520,7 +547,8 @@ function initializeDatatable (status) {
// Parameters
'pageLength' : tableRows,
'order' : tableOrder,
'order' : tableOrder,
'select' : true, // Enable selection
'columnDefs' : [
{visible: false, targets: tableColumnHide },
@@ -556,7 +584,7 @@ function initializeDatatable (status) {
{targets: [mapIndx(3)],
'createdCell': function (td, cellData, rowData, row, col) {
if (!emptyArr.includes(cellData)){
$(td).html ('<i class="fa fa-'+cellData+' " style="font-size:16px"></i>');
$(td).html (atob(cellData));
} else {
$(td).html ('');
}
@@ -656,6 +684,29 @@ function initializeDatatable (status) {
setCache ('devicesList', getDevicesFromTable(table) );
} );
// 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>`)
// Event listener for row selection in DataTable
$('#tableDevices').on('click', 'tr', function (e) {
setTimeout(function(){
// Check if any row is selected
var anyRowSelected = $('#tableDevices tr.selected').length > 0;
console.log(anyRowSelected);
// Toggle visibility of element with ID 'multiEdit'
$('#multiEdit').toggle(anyRowSelected);
}, 200);
});
hideSpinner();
});
};
@@ -697,7 +748,7 @@ function getNumberOfChildren(mac, devices)
$.each(devices, function(index, dev) {
if(dev.dev_Network_Node_MAC_ADDR.trim() == mac.trim())
if(dev.dev_Network_Node_MAC_ADDR != null && dev.dev_Network_Node_MAC_ADDR.trim() == mac.trim())
{
childrenCount++;
}
@@ -708,27 +759,111 @@ function getNumberOfChildren(mac, devices)
}
// -----------------------------------------------------------------------------
function handleLoadingDialog()
function handleLoadingDialog(needsReload = false)
{
$.get('log/execution_queue.log?nocache=' + Date.now(), function(data) {
// console.log('needsReload:');
// console.log(needsReload);
$.get('log/execution_queue.log?nocache=' + Date.now(), function(data) {
if(data.includes("update_api|devices"))
{
showSpinner("devices_old")
setTimeout("handleLoadingDialog()", 1000);
setTimeout(handleLoadingDialog(true), 1000);
} else if ($("#loadingSpinner").is(":visible"))
} else if (needsReload)
{
location.reload();
}else
{
hideSpinner();
location.reload();
// hideSpinner();
}
})
}
// -----------------------------------------------------------------------------
// Function collects selected devices in the DataTable and redirects the user to
// the Miantenance section with a 'macs' query string identifying selected devices
function multiEditDevices()
{
rows = $('#tableDevices')[0].rows
// Initialize an empty array to store selected rows
var selectedRows = [];
// console.log($('#tableDevices')[0].rows);
// Loop through each row in the HTML collection
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
// Check if the row has the 'selected' class
if (row.classList.contains('selected')) {
// If selected, push the row's data to the selectedRows array
selectedRows.push(row);
}
}
// Now, selectedRows contains all selected rows
console.log(selectedRows);
var devicesDataTableData = $('#tableDevices').dataTable().fnGetData();
var selectedDevices = [];
for (var i = 0; i < selectedRows.length; i++) {
selectedDevices.push(devicesDataTableData[selectedRows[i]._DT_RowIndex]);
}
// Now, selectedDevices contains all selected devices
// console.log(selectedDevices);
macs = ""
for (var i = 0; i < selectedDevices.length; i++) {
macs += selectedDevices[i][mapIndx(11)] + ","; // [11] == MAC
}
// redirect to the Maintenance section
window.location.href = window.location.origin + '/maintenance.php#tab_multiEdit?macs=' + macs.slice(0, -1);
}
// -----------------------------------------------------------------------------
// Function collects shown devices from the DataTable
function getMacsOfShownDevices() {
rows = $('#tableDevices')[0].rows
macs = []
var devicesDataTableData = $('#tableDevices').dataTable().fnGetData();
var selectedDevices = [];
for (var i = 0; i < rows.length; i++) {
selectedDevices.push(devicesDataTableData[rows[i]._DT_RowIndex]);
}
for (var i = 1; i < selectedDevices.length; i++) {
macs.push(selectedDevices[i][mapIndx(11)]); // mapIndx(11) == MAC
}
return macs;
}
// -----------------------------------------------------------------------------
// Update cahce with shown devices before navigating away
window.addEventListener('beforeunload', function(event) {
// Call your function here
macs = getMacsOfShownDevices();
setCache("ntx_visible_macs", macs)
});
</script>
<script src="js/pialert_common.js"></script>

View File

@@ -1,7 +1,7 @@
<?php
require 'php/templates/header.php';
?>
<script src="js/pialert_common.js"></script>
<div id="donationsPage" class="content-wrapper">
<!-- Content header--------------------------------------------------------- -->
<section class="content-header">

View File

@@ -1,6 +1,6 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# events.php - Front module. Events page #

BIN
front/img/NetAlertX_logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,6 +1,6 @@
{
"name": "Pi-Alert Console",
"short_name": "Pi-Alert",
"name": "NetAlertX Console",
"short_name": "NetAlertX",
"display": "standalone",
"icons": [
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,11 +1,11 @@
<!-- Pi.Alert CSS -->
<link rel="stylesheet" href="css/pialert.css">
<!-- NetAlertX CSS -->
<link rel="stylesheet" href="css/app.css">
<?php
require dirname(__FILE__).'/php/server/init.php';
require 'php/templates/security.php';
$CookieSaveLoginName = 'NetAlertX_SaveLogin';
if ($Pia_WebProtection != 'true')
{
@@ -17,7 +17,7 @@ if ($Pia_WebProtection != 'true')
// Logout
if (isset ($_GET["action"]) && $_GET["action"] == 'logout')
{
setcookie("PiAlert_SaveLogin", '', time()+1); // reset cookie
setcookie($CookieSaveLoginName, '', time()+1); // reset cookie
$_SESSION["login"] = 0;
header('Location: index.php');
exit;
@@ -28,15 +28,15 @@ if (isset ($_POST["loginpassword"]) && $Pia_Password == hash('sha256',$_POST["lo
{
header('Location: devices.php');
$_SESSION["login"] = 1;
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
if (isset($_POST['PWRemember'])) {setcookie($CookieSaveLoginName, hash('sha256',$_POST["loginpassword"]), time()+604800);}
}
// active Session or valid cookie (cookie not extends)
if (( isset ($_SESSION["login"]) && ($_SESSION["login"] == 1)) || (isset ($_COOKIE["PiAlert_SaveLogin"]) && $Pia_Password == $_COOKIE["PiAlert_SaveLogin"]))
if (( isset ($_SESSION["login"]) && ($_SESSION["login"] == 1)) || (isset ($_COOKIE[$CookieSaveLoginName]) && $Pia_Password == $_COOKIE[$CookieSaveLoginName]))
{
header('Location: devices.php');
$_SESSION["login"] = 1;
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
if (isset($_POST['PWRemember'])) {setcookie($CookieSaveLoginName, hash('sha256',$_POST["loginpassword"]), time()+604800);}
}
$login_headline = lang('Login_Toggle_Info_headline');
@@ -84,7 +84,7 @@ if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
<!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/bootstrap/dist/css/bootstrap.min.css">
<!-- Font Awesome -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="lib/AdminLTE/bower_components/font-awesome/css/fontawesome.min.css">
<!-- Ionicons -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/Ionicons/css/ionicons.min.css">
<!-- Theme style -->
@@ -99,13 +99,12 @@ if ($ENABLED_DARKMODE === True) {
$BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/boxed-bg-dark.png\');"';
} else { $BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/background.png\');"';}
?>
<link rel="stylesheet" href="/front/css/offline-font.css">
<link rel="stylesheet" href="/css/offline-font.css">
</head>
<body class="hold-transition login-page">
<div class="login-box login-custom">
<div class="login-logo">
<a href="/index2.php">Pi.<b>Alert</b></a>
<a href="/index2.php">Net <b>Alert</b><sup>x</sup></a>
</div>
<!-- /.login-logo -->
<div class="login-box-body">
@@ -148,7 +147,7 @@ if ($ENABLED_DARKMODE === True) {
<button type="button" class="close" data-dismiss="alert" aria-hidden="true"><3E></button>
<h4><i class="icon fa <?php echo $login_icon;?>"></i><?php echo $login_headline;?></h4>
<p><?php echo $login_info;?></p>
<p><?= lang('Login_Psw_run');?><br><span style="border: solid 1px yellow; padding: 2px;"> /home/pi/pialert/back/pialert-cli set_password <?= lang('Login_Psw_new');?></span><br><?= lang('Login_Psw_folder');?></p>
<p><?= lang('Login_Psw_run');?><br><span style="border: solid 1px yellow; padding: 2px;"> /app/back/pialert-cli set_password <?= lang('Login_Psw_new');?></span><br><?= lang('Login_Psw_folder');?></p>
</div>
</div>

1344
front/js/common.js Executable file

File diff suppressed because it is too large Load Diff

18
front/js/db_methods.js Executable file
View File

@@ -0,0 +1,18 @@
// -----------------------------------------------------------------------------
// General utilities to interact with teh database
// -----------------------------------------------------------------------------
// Read data and place intotarget location, callback processies the results
function readData(sqlQuery, processDataCallback, valuesArray, targetLocation, targetField, nameTransformer) {
var apiUrl = `php/server/dbHelper.php?action=read&rawSql=${encodeURIComponent(sqlQuery)}`;
$.get(apiUrl, function(data) {
// Process the JSON data using the provided callback function
data = JSON.parse(data)
var htmlResult = processDataCallback(data, valuesArray, targetField, nameTransformer);
// Place the resulting HTML into the specified placeholder div
$("#" + targetLocation).replaceWith(htmlResult);
});
}

View File

@@ -1,32 +1,70 @@
function pia_draw_graph_online_history(pia_js_graph_online_history_time, pia_js_graph_online_history_ondev, pia_js_graph_online_history_dodev, pia_js_graph_online_history_ardev) {
var xValues = pia_js_graph_online_history_time;
// alert("dev presence")
// Data object for online status
onlineData = {
label: 'Online',
data: pia_js_graph_online_history_ondev,
borderColor: "rgba(0, 166, 89)",
fill: true,
backgroundColor: "rgba(0, 166, 89, .6)",
pointStyle: 'circle',
pointRadius: 3,
pointHoverRadius: 3
};
// Data object for offline status
offlineData = {
label: 'Offline/Down',
data: pia_js_graph_online_history_dodev,
borderColor: "rgba(222, 74, 56)",
fill: true,
backgroundColor: "rgba(222, 74, 56, .6)",
};
// Data object for archived status
archivedData = {
label: 'Archived',
data: pia_js_graph_online_history_ardev,
borderColor: "rgba(220,220,220)",
fill: true,
backgroundColor: "rgba(220,220,220, .6)",
};
// Array to store datasets
datasets = [];
// Get UI presence settings
showStats = getSetting("UI_PRESENCE");
// Check if 'online' status should be displayed
if(showStats.includes("online"))
{
datasets.push(onlineData); // Add onlineData to datasets array
}
// Check if 'offline' status should be displayed
if(showStats.includes("offline"))
{
datasets.push(offlineData); // Add offlineData to datasets array
}
// Check if 'archived' status should be displayed
if(showStats.includes("archived"))
{
datasets.push(archivedData); // Add archivedData to datasets array
}
new Chart("OnlineChart", {
type: "bar",
scaleIntegersOnly: true,
data: {
labels: xValues,
datasets: [{
label: 'Online',
data: pia_js_graph_online_history_ondev,
borderColor: "rgba(0, 166, 89)",
fill: true,
backgroundColor: "rgba(0, 166, 89, .6)",
pointStyle: 'circle',
pointRadius: 3,
pointHoverRadius: 3
}, {
label: 'Offline/Down',
data: pia_js_graph_online_history_dodev,
borderColor: "rgba(222, 74, 56)",
fill: true,
backgroundColor: "rgba(222, 74, 56, .6)",
}, {
label: 'Archived',
data: pia_js_graph_online_history_ardev,
borderColor: "rgba(220,220,220)",
fill: true,
backgroundColor: "rgba(220,220,220, .6)",
}]
datasets: datasets
},
options: {
legend: {

View File

@@ -4,7 +4,7 @@ function versionUpdateUI(){
isNewVersion = getCookie("isNewVersion")
console.log(isNewVersion)
// console.log(isNewVersion)
// if the release_timestamp is older by 10 min or more as the build timestamp then there is a new release available
if(isNewVersion != "false")
@@ -35,8 +35,8 @@ function checkIfNewVersionAvailable()
{
$.get('api/app_state.json?nocache=' + Date.now(), function(appState) {
console.log(appState["isNewVersionChecked"])
console.log(appState["isNewVersion"])
// console.log(appState["isNewVersionChecked"])
// console.log(appState["isNewVersion"])
// cache value
setCookie("isNewVersion", appState["isNewVersion"], 30);

View File

@@ -1,782 +0,0 @@
/* -----------------------------------------------------------------------------
* Pi.Alert
* Open Source Network Guard / WIFI & LAN intrusion detector
*
* pialert_common.js - Front module. Common Javascript functions
*-------------------------------------------------------------------------------
# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3
----------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
var timerRefreshData = ''
var modalCallbackFunction = '';
var emptyArr = ['undefined', "", undefined, null, 'null'];
var UI_LANG = "English";
var settingsJSON = {}
// urlParams = new Proxy(new URLSearchParams(window.location.search), {
// get: (searchParams, prop) => searchParams.get(prop.toString()),
// });
// -----------------------------------------------------------------------------
// Simple session cache withe expiration managed via cookies
// -----------------------------------------------------------------------------
function getCache(key, noCookie = false)
{
// check cache
if(sessionStorage.getItem(key))
{
// check if not expired
if(noCookie || getCookie(key + '_session_expiry') != "")
{
return sessionStorage.getItem(key);
}
}
return "";
}
// -----------------------------------------------------------------------------
function setCache(key, data, expirationMinutes='')
{
sessionStorage.setItem(key, data);
// create cookie if expiration set to handle refresh of data
if (expirationMinutes != '')
{
setCookie (key + '_session_expiry', 'OK', expirationMinutes='')
}
}
// -----------------------------------------------------------------------------
function setCookie (cookie, value, expirationMinutes='') {
// Calc expiration date
var expires = '';
if (typeof expirationMinutes === 'number') {
expires = ';expires=' + new Date(Date.now() + expirationMinutes *60*1000).toUTCString();
}
// Save Cookie
document.cookie = cookie + "=" + value + expires;
}
// -----------------------------------------------------------------------------
function getCookie (cookie) {
// Array of cookies
var allCookies = document.cookie.split(';');
// For each cookie
for (var i = 0; i < allCookies.length; i++) {
var currentCookie = allCookies[i].trim();
// If the current cookie is the correct cookie
if (currentCookie.indexOf (cookie +'=') == 0) {
// Return value
return currentCookie.substring (cookie.length+1);
}
}
// Return empty (not found)
return "";
}
// -----------------------------------------------------------------------------
function deleteCookie (cookie) {
document.cookie = cookie + '=;expires=Thu, 01 Jan 1970 00:00:00 UTC';
}
// -----------------------------------------------------------------------------
function deleteAllCookies() {
// Array of cookies
var allCookies = document.cookie.split(";");
// For each cookie
for (var i = 0; i < allCookies.length; i++) {
var cookie = allCookies[i].trim();
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC";
}
}
// -----------------------------------------------------------------------------
// Get settings from the .json file generated by the python backend
// -----------------------------------------------------------------------------
function cacheSettings()
{
$.get('api/table_settings.json', function(res) {
settingsJSON = res;
data = settingsJSON["data"];
data.forEach((set) => {
setCache(`pia_set_${set.Code_Name}`, set.Value)
});
})
}
function getSetting (key) {
result = getCache(`pia_set_${key}`, true);
if (result == "")
{
console.log(`Setting with key "${key}" not found`)
}
return result;
}
// -----------------------------------------------------------------------------
// Get language string
// -----------------------------------------------------------------------------
function cacheStrings()
{
// handle core strings and translations
var allLanguages = ["en_us", "es_es", "de_de"]; // needs to be same as in lang.php
allLanguages.forEach(function (language_code) {
$.get(`php/templates/language/${language_code}.json`, function (res) {
// Iterate over each language
Object.entries(res).forEach(([key, value]) => {
// Store translations for each key-value pair
setCache(`pia_lang_${key}_${language_code}`, value)
});
});
});
// handle strings and translations from plugins
$.get('api/table_plugins_language_strings.json', function(res) {
data = res["data"];
data.forEach((langString) => {
setCache(`pia_lang_${langString.String_Key}_${langString.Language_Code}`, langString.String_Value)
});
})
}
// Get translated language string
function getString (key) {
UI_LANG = getSetting("UI_LANG");
lang_code = 'en_us';
switch(UI_LANG)
{
case 'English':
lang_code = 'en_us';
break;
case 'Spanish':
lang_code = 'es_es';
break;
case 'German':
lang_code = 'de_de';
break;
}
result = getCache(`pia_lang_${key}_${lang_code}`, true);
if(isEmpty(result))
{
result = getCache(`pia_lang_${key}_en_us`, true);
}
return result;
}
// -----------------------------------------------------------------------------
// Modal dialog handling
// -----------------------------------------------------------------------------
function showModalOK (title, message, callbackFunction) {
showModalOk (title, message, callbackFunction)
}
function showModalOk (title, message, callbackFunction) {
// set captions
$('#modal-ok-title').html (title);
$('#modal-ok-message').html (message);
if(callbackFunction!= null)
{
$("#modal-ok-OK").click(function()
{
callbackFunction()
});
}
// Show modal
$('#modal-ok').modal('show');
}
// -----------------------------------------------------------------------------
function showModalDefault (title, message, btnCancel, btnOK, callbackFunction) {
// set captions
$('#modal-default-title').html (title);
$('#modal-default-message').html (message);
$('#modal-default-cancel').html (btnCancel);
$('#modal-default-OK').html (btnOK);
modalCallbackFunction = callbackFunction;
// Show modal
$('#modal-default').modal('show');
}
// -----------------------------------------------------------------------------
function showModalDefaultStrParam (title, message, btnCancel, btnOK, callbackFunction, param='') {
// set captions
$('#modal-str-title').html (title);
$('#modal-str-message').html (message);
$('#modal-str-cancel').html (btnCancel);
$('#modal-str-OK').html (btnOK);
$("#modal-str-OK").off("click"); //remove existing handlers
$('#modal-str-OK').on('click', function (){
$('#modal-str').modal('hide');
callbackFunction(param)
})
// Show modal
$('#modal-str').modal('show');
}
// -----------------------------------------------------------------------------
function showModalWarning (title, message, btnCancel=getString('Gen_Cancel'), btnOK=getString('Gen_Okay'), callbackFunction=null) {
// set captions
$('#modal-warning-title').html (title);
$('#modal-warning-message').html (message);
$('#modal-warning-cancel').html (btnCancel);
$('#modal-warning-OK').html (btnOK);
if ( callbackFunction != null)
{
modalCallbackFunction = callbackFunction;
}
// Show modal
$('#modal-warning').modal('show');
}
// -----------------------------------------------------------------------------
function modalDefaultOK () {
// Hide modal
$('#modal-default').modal('hide');
// timer to execute function
window.setTimeout( function() {
window[modalCallbackFunction]();
}, 100);
}
// -----------------------------------------------------------------------------
function modalWarningOK () {
// Hide modal
$('#modal-warning').modal('hide');
// timer to execute function
window.setTimeout( function() {
window[modalCallbackFunction]();
}, 100);
}
// -----------------------------------------------------------------------------
function showMessage (textMessage="") {
if (textMessage.toLowerCase().includes("error") ) {
// show error
alert (textMessage);
} else {
// show temporal notification
$("#alert-message").html (textMessage);
$("#notification").fadeIn(1, function () {
window.setTimeout( function() {
$("#notification").fadeOut(500)
}, 3000);
} );
}
}
// -----------------------------------------------------------------------------
// String utilities
// -----------------------------------------------------------------------------
function jsonSyntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
// -----------------------------------------------------------------------------
// General utilities
// -----------------------------------------------------------------------------
// check if JSON object
function isJsonObject(value) {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
// remove unnecessary lines from the result
function sanitize(data)
{
return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "")
}
// -----------------------------------------------------------------------------
// Check and handle locked database
function handle_locked_DB(data)
{
if(data.includes('database is locked'))
{
console.log(data)
showSpinner()
setTimeout(function() {
location.reload();
}, 5000);
}
}
// -----------------------------------------------------------------------------
function numberArrayFromString(data)
{
data = JSON.parse(sanitize(data));
return data.replace(/\[|\]/g, '').split(',').map(Number);
}
// -----------------------------------------------------------------------------
function setParameter (parameter, value) {
// Retry
$.get('php/server/parameters.php?action=set&parameter=' + parameter +
'&value='+ value,
function(data) {
if (data != "OK") {
// Retry
sleep (200);
$.get('php/server/parameters.php?action=set&parameter=' + parameter +
'&value='+ value,
function(data) {
if (data != "OK") {
// alert (data);
} else {
// alert ("OK. Second attempt");
};
} );
};
} );
}
// -----------------------------------------------------------------------------
function saveData(functionName, id, value) {
$.ajax({
method: "GET",
url: "php/server/devices.php",
data: { action: functionName, id: id, value:value },
success: function(data) {
if(sanitize(data) == 'OK')
{
showMessage("Saved")
// Remove navigation prompt "Are you sure you want to leave..."
window.onbeforeunload = null;
} else
{
showMessage("ERROR")
}
}
});
}
// -----------------------------------------------------------------------------
// create a link to the device
function createDeviceLink(input)
{
if(checkMacOrInternet(input))
{
return `<span class="anonymizeMac"><a href="/deviceDetails.php?mac=${input}" target="_blank">${getNameByMacAddress(input)}</a><span>`
}
return input;
}
// -----------------------------------------------------------------------------
// remove an item from an array
function removeItemFromArray(arr, value) {
var index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
// -----------------------------------------------------------------------------
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
// ---------------------------------------------------------
somethingChanged = false;
function settingsChanged()
{
somethingChanged = true;
// Enable navigation prompt ... "Are you sure you want to leave..."
window.onbeforeunload = function() {
return true;
};
}
// -----------------------------------------------------------------------------
function getQueryString(key){
params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
tmp = params[key]
result = emptyArr.includes(tmp) ? "" : tmp;
return result
}
// -----------------------------------------------------------------------------
function translateHTMLcodes (text) {
if (text == null || emptyArr.includes(text)) {
return null;
} else if (typeof text === 'string' || text instanceof String)
{
var text2 = text.replace(new RegExp(' ', 'g'), "&nbsp");
text2 = text2.replace(new RegExp('<', 'g'), "&lt");
return text2;
}
return "";
}
// -----------------------------------------------------------------------------
function stopTimerRefreshData () {
try {
clearTimeout (timerRefreshData);
} catch (e) {}
}
// -----------------------------------------------------------------------------
function newTimerRefreshData (refeshFunction) {
timerRefreshData = setTimeout (function() {
refeshFunction();
}, 60000);
}
// -----------------------------------------------------------------------------
function debugTimer () {
$('#pageTitle').html (new Date().getSeconds());
}
// -----------------------------------------------------------------------------
function openInNewTab (url) {
window.open(url, "_blank");
}
// -----------------------------------------------------------------------------
function navigateToDeviceWithIp (ip) {
$.get('api/table_devices.json', function(res) {
devices = res["data"];
mac = ""
$.each(devices, function(index, obj) {
if(obj.dev_LastIP.trim() == ip.trim())
{
mac = obj.dev_MAC;
window.open(window.location.origin +'/deviceDetails.php?mac=' + mac , "_blank");
}
});
});
}
// -----------------------------------------------------------------------------
function getNameByMacAddress(macAddress) {
return getDeviceDataByMacAddress(macAddress, "dev_Name")
}
// -----------------------------------------------------------------------------
// Check if MAC or Internet
function checkMacOrInternet(inputStr) {
// Regular expression pattern for matching a MAC address
const macPattern = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
if (inputStr.toLowerCase() === 'internet') {
return true;
} else if (macPattern.test(inputStr)) {
return true;
} else {
return false;
}
}
// -----------------------------------------------------------------------------
// A function used to make the IP address orderable
function isValidIPv6(ipAddress) {
// Regular expression for IPv6 validation
const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}$|^([0-9a-fA-F]{1,4}:){1,7}:|^([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}$|^([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}$|^([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}$|^([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})$/;
return ipv6Regex.test(ipAddress);
}
function formatIPlong(ipAddress) {
if (ipAddress.includes(':') && isValidIPv6(ipAddress)) {
const parts = ipAddress.split(':');
return parts.reduce((acc, part, index) => {
if (part === '') {
const remainingGroups = 8 - parts.length + 1;
return acc << (16 * remainingGroups);
}
const hexValue = parseInt(part, 16);
return acc | (hexValue << (112 - index * 16));
}, 0);
} else {
// Handle IPv4 address
const parts = ipAddress.split('.');
if (parts.length !== 4) {
console.log("⚠ Invalid IPv4 address: " + ipAddress);
return -1; // or any other default value indicating an error
}
return (parseInt(parts[0]) << 24) |
(parseInt(parts[1]) << 16) |
(parseInt(parts[2]) << 8) |
parseInt(parts[3]);
}
}
// -----------------------------------------------------------------------------
// Check if MAC is a random one
function isRandomMAC(mac)
{
isRandom = false;
isRandom = ["2", "6", "A", "E", "a", "e"].includes(mac[1]);
// if detected as random, make sure it doesn't start with a prefix which teh suer doesn't want to mark as random
if(isRandom)
{
$.each(createArray(getSetting("UI_NOT_RANDOM_MAC")), function(index, prefix) {
if(mac.startsWith(prefix))
{
isRandom = false;
}
});
}
return isRandom;
}
// ---------------------------------------------------------
// Generate an array object from a string representation of an array
function createArray(input) {
// Empty array
if (input === '[]') {
return [];
}
// Regex patterns
const patternBrackets = /(^\s*\[)|(\]\s*$)/g;
const patternQuotes = /(^\s*')|('\s*$)/g;
const replacement = '';
// Remove brackets
const noBrackets = input.replace(patternBrackets, replacement);
const options = [];
// Create array
const optionsTmp = noBrackets.split(',');
// Handle only one item in array
if (optionsTmp.length === 0) {
return [noBrackets.replace(patternQuotes, replacement)];
}
// Remove quotes
optionsTmp.forEach(item => {
options.push(item.replace(patternQuotes, replacement).trim());
});
return options;
}
// -----------------------------------------------------------------------------
// A function to get a device property using the mac address as key and DB column nakme as parameter
// for the value to be returned
function getDeviceDataByMacAddress(macAddress, dbColumn) {
const sessionDataKey = 'devicesListAll_JSON';
const sessionData = sessionStorage.getItem(sessionDataKey);
if (!sessionData) {
console.log(`Session variable "${sessionDataKey}" not found.`);
return "Unknown";
}
const devices = JSON.parse(sessionData);
for (const device of devices) {
if (device["dev_MAC"].toLowerCase() === macAddress.toLowerCase()) {
return device[dbColumn];
}
}
return "Unknown"; // Return a default value if MAC address is not found
}
// -----------------------------------------------------------------------------
function initDeviceListAll_JSON()
{
$.get('api/table_devices.json', function(data) {
console.log(data)
devicesListAll_JSON = data["data"]
setCache('devicesListAll_JSON', JSON.stringify(devicesListAll_JSON))
});
}
var devicesListAll_JSON = []; // this will contain a list off all devices
// -----------------------------------------------------------------------------
function isEmpty(value)
{
return emptyArr.includes(value)
}
// -----------------------------------------------------------------------------
// Generate a GUID
function getGuid() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
// -----------------------------------------------------------------------------
// UI
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Genrate work-in-progress icons
function workInProgress() {
console.log()
if($(".work-in-progress").html().trim() == "")
{
$(".work-in-progress").append(`
<a href="https://github.com/jokob-sk/Pi.Alert/issues" target="_blank">
<b class="pointer" title="${getString("Gen_Work_In_Progress")}">🦺</b>
</a>
`)
}
}
// -----------------------------------------------------------------------------
// Loading Spinner overlay
// -----------------------------------------------------------------------------
function showSpinner(stringKey='Loading')
{
if($("#loadingSpinner").length)
{
$("#loadingSpinner").show();
}
else{
html = `
<!-- spinner -->
<div id="loadingSpinner" style="display: block">
<div class="pa_semitransparent-panel"></div>
<div class="panel panel-default pa_spinner">
<table>
<td width="130px" align="middle">${getString(stringKey)}</td>
<td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td>
</table>
</div>
</div>
`
$(".wrapper").append(html)
}
}
// -----------------------------------------------------------------------------
function hideSpinner()
{
$("#loadingSpinner").hide()
}
// -----------------------------------------------------------------------------
// initialize
// -----------------------------------------------------------------------------
cacheSettings()
cacheStrings()
initDeviceListAll_JSON()
workInProgress()
console.log("init pialert_common.js")

View File

@@ -163,4 +163,9 @@
}
return true; // Return true if no schedules are found
}
}

286
front/js/ui_components.js Executable file
View File

@@ -0,0 +1,286 @@
/* -----------------------------------------------------------------------------
* NetAlertX
* Open Source Network Guard / WIFI & LAN intrusion detector
*
* ui_components.js - Front module. Common UI components
*-------------------------------------------------------------------------------
# jokob jokob@duck.com GNU GPLv3
----------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
// Initialize device selectors / pickers fields
// -----------------------------------------------------------------------------
function initDeviceSelectors() {
console.log(devicesList)
// Retrieve device list from session variable
var devicesListAll_JSON = getCache('devicesListAll_JSON');
var devicesList = JSON.parse(devicesListAll_JSON);
console.log(devicesList);
// Check if both device list exists
if (devicesListAll_JSON) {
// Parse the JSON string to get the device list array
var devicesList = JSON.parse(devicesListAll_JSON);
var selectorFieldsHTML = ''
// Loop through the devices list
devicesList.forEach(function(device) {
selectorFieldsHTML += `<option value="${device.dev_MAC}">${device.dev_Name}</option>`;
});
selector = `<div class="db_info_table_row col-sm-12" >
<div class="form-group" >
<div class="input-group col-sm-12 " >
<select class="form-control select2 select2-hidden-accessible" multiple="" style="width: 100%;" tabindex="-1" aria-hidden="true">
${selectorFieldsHTML}
</select>
</div>
</div>
</div>`
// Find HTML elements with class "deviceSelector" and append selector field
$('.deviceSelector').append(selector);
}
// Initialize selected items after a delay so selected macs are available in the context
setTimeout(function(){
// Retrieve MAC addresses from query string or cache
var macs = getQueryString('macs') || getCache('selectedDevices');
if(macs)
{
// Split MAC addresses if they are comma-separated
macs = macs.split(',');
console.log(macs)
// Loop through macs to be selected list
macs.forEach(function(mac) {
// Create the option and append to Select2
var option = new Option($('.deviceSelector select option[value="' + mac + '"]').html(), mac, true, true);
$('.deviceSelector select').append(option).trigger('change');
});
}
}, 10);
}
// --------------------------------------------------------
//Initialize Select2 Elements and make them sortable
$(function () {
// Iterate over each Select2 dropdown
$('.select2').each(function() {
var selectEl = $(this).select2();
// Apply sortable functionality to the dropdown's dropdown-container
selectEl.next().children().children().children().sortable({
containment: 'parent',
update: function () {
var sortedValues = $(this).children().map(function() {
return $(this).attr('title');
}).get();
var sortedOptions = selectEl.find('option').sort(function(a, b) {
return sortedValues.indexOf($(a).text()) - sortedValues.indexOf($(b).text());
});
// Replace all options in selectEl
selectEl.empty().append(sortedOptions);
// Trigger change event on Select2
selectEl.trigger('change');
}
});
});
});
// -----------------------------------------------------------------------------
// Initiate dropdown
function initSettingDropdown(settingKey, // Identifier for the setting
valuesArray, // Array of values to be pre-selected in the dropdown
targetLocation, // ID of the HTML element where dropdown should be rendered (will be replaced)
callbackToGenerateEntries, // Callback function to generate entries based on options
targetField, // Target field or element where selected value should be applied or updated
nameTransformer) // callback to transform the name (e.g. base64)
{
var optionsHtml = ""
optionsArray = createArray(getSettingOptions(settingKey))
// check if the result is a SQL query
if(isSQLQuery(optionsArray[0]))
{
readData(optionsArray[0], callbackToGenerateEntries, valuesArray, targetLocation, targetField, nameTransformer);
} else // this should be already an array, e.g. from a setting or pre-defined
{
optionsArray.forEach(option => {
let selected = valuesArray.includes(option) ? 'selected' : '';
optionsHtml += `<option value="${option}" ${selected}>${option}</option>`;
});
// Replace the specified placeholder div with the resulting HTML
setTimeout(() => {
$("#" + targetLocation).replaceWith(optionsHtml);
}, 50);
}
}
// -----------------------------------------------------------------------------
// Hide elements on the page based on the supplied setting
function hideUIelements(settingKey) {
hiddenSectionsSetting = getSetting(settingKey)
if(hiddenSectionsSetting != "") // handle if settings not yet initialized
{
sectionsArray = createArray(hiddenSectionsSetting)
// remove spaces to get IDs
var newArray = $.map(sectionsArray, function(value) {
return value.replace(/\s/g, '');
});
$.each(newArray, function(index, hiddenSection) {
if($('#' + hiddenSection))
{
$('#' + hiddenSection).hide()
}
});
}
}
// -----------------------------------------------------------------------------
// Data processors
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Processor to generate options for a dropdown menu
function generateDropdownOptions(data, valuesArray, targetField, nameTransformer) {
var optionsHtml = "";
data.forEach(function(item) {
labelName = item.name
// console.log(nameTransformer);
// console.log(labelName);
// if(nameTransformer && nameTransformer != '' && labelName != '❌None')
// {
// console.log(labelName);
// labelName = nameTransformer(labelName)
// console.log(labelName);
// }
let selected = valuesArray.includes(item.id) ? 'selected' : '';
optionsHtml += `<option value="${item.id}" ${selected}>${labelName}</option>`;
});
return `${optionsHtml}`;
}
// -----------------------------------------------------------------------------
// Processor to generate a list
function generateList(data, valuesArray, targetField, nameTransformer) {
var listHtml = "";
data.forEach(function(item) {
labelName = item.name
if(nameTransformer && nameTransformer != '' && labelName != '❌None')
{
labelName = nameTransformer(labelName)
}
let selected = valuesArray.includes(item.id) ? 'selected' : '';
listHtml += `<li ${selected}>${labelName}</li>`;
});
return listHtml;
}
// -----------------------------------------------------------------------------
// Processor to generate a list in the deviceDetails page
function genListWithInputSet(data, valuesArray, targetField, nameTransformer) {
var listHtml = "";
console.log(data);
data.forEach(function(item) {
let selected = valuesArray.includes(item.id) ? 'selected' : '';
console.log(item);
labelName = item.name
if(nameTransformer && nameTransformer != '' && labelName != '❌None')
{
labelName = nameTransformer(labelName)
}
listHtml += `<li ${selected}>
<a href="javascript:void(0)" onclick="setTextValue('${targetField}','${item.id}')">${labelName}</a>
</li>`;
});
return listHtml;
}
// -----------------------------------------------------------------------------
// Updates the icon preview
function updateIconPreview (inputId) {
// update icon
iconInput = $(inputId)
value = iconInput.val()
iconInput.on('change input', function() {
$('#txtIconFA').html(atob(value))
});
$('#txtIconFA').html(atob(value))
}
// -----------------------------------------------------------------------------
// initialize
// -----------------------------------------------------------------------------
initDeviceSelectors();
console.log("init ui_components.js")

View File

@@ -0,0 +1 @@
table.dataTable tbody>tr.selected,table.dataTable tbody>tr>.selected{background-color:#b0bed9}table.dataTable.stripe tbody>tr.odd.selected,table.dataTable.stripe tbody>tr.odd>.selected,table.dataTable.display tbody>tr.odd.selected,table.dataTable.display tbody>tr.odd>.selected{background-color:#acbad4}table.dataTable.hover tbody>tr.selected:hover,table.dataTable.hover tbody>tr>.selected:hover,table.dataTable.display tbody>tr.selected:hover,table.dataTable.display tbody>tr>.selected:hover{background-color:#aab7d1}table.dataTable.order-column tbody>tr.selected>.sorting_1,table.dataTable.order-column tbody>tr.selected>.sorting_2,table.dataTable.order-column tbody>tr.selected>.sorting_3,table.dataTable.order-column tbody>tr>.selected,table.dataTable.display tbody>tr.selected>.sorting_1,table.dataTable.display tbody>tr.selected>.sorting_2,table.dataTable.display tbody>tr.selected>.sorting_3,table.dataTable.display tbody>tr>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody>tr.odd>.selected,table.dataTable.order-column.stripe tbody>tr.odd>.selected{background-color:#a6b4cd}table.dataTable.display tbody>tr.even>.selected,table.dataTable.order-column.stripe tbody>tr.even>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.selected:hover>.sorting_1,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody>tr.selected:hover>.sorting_2,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody>tr.selected:hover>.sorting_3,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_3{background-color:#a5b2cb}table.dataTable.display tbody>tr:hover>.selected,table.dataTable.display tbody>tr>.selected:hover,table.dataTable.order-column.hover tbody>tr:hover>.selected,table.dataTable.order-column.hover tbody>tr>.selected:hover{background-color:#a2aec7}table.dataTable tbody td.select-checkbox,table.dataTable tbody th.select-checkbox{position:relative}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody td.select-checkbox:after,table.dataTable tbody th.select-checkbox:before,table.dataTable tbody th.select-checkbox:after{display:block;position:absolute;top:1.2em;left:50%;width:12px;height:12px;box-sizing:border-box}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody th.select-checkbox:before{content:" ";margin-top:-6px;margin-left:-6px;border:1px solid black;border-radius:3px}table.dataTable tr.selected td.select-checkbox:after,table.dataTable tr.selected th.select-checkbox:after{content:"✓";font-size:20px;margin-top:-19px;margin-left:-6px;text-align:center;text-shadow:1px 1px #b0bed9,-1px -1px #b0bed9,1px -1px #b0bed9,-1px 1px #b0bed9}table.dataTable.compact tbody td.select-checkbox:before,table.dataTable.compact tbody th.select-checkbox:before{margin-top:-12px}table.dataTable.compact tr.selected td.select-checkbox:after,table.dataTable.compact tr.selected th.select-checkbox:after{margin-top:-16px}div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:.5em}@media screen and (max-width: 640px){div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:0;display:block}}

View File

@@ -0,0 +1,38 @@
/*!
Copyright 2015-2021 SpryMedia Ltd.
This source file is free software, available under the following license:
MIT license - http://datatables.net/license/mit
This source file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
For details please refer to: http://www.datatables.net/extensions/select
Select for DataTables 1.3.3
2015-2021 SpryMedia Ltd - datatables.net/license/mit
*/
(function(h){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(q){return h(q,window,document)}):"object"===typeof exports?module.exports=function(q,t){q||(q=window);t&&t.fn.dataTable||(t=require("datatables.net")(q,t).$);return h(t,q,q.document)}:h(jQuery,window,document)})(function(h,q,t,n){function E(a,b,c){var d=function(g,f){if(g>f){var k=f;f=g;g=k}var l=!1;return a.columns(":visible").indexes().filter(function(p){p===g&&(l=!0);return p===f?(l=!1,!0):l})};var e=
function(g,f){var k=a.rows({search:"applied"}).indexes();if(k.indexOf(g)>k.indexOf(f)){var l=f;f=g;g=l}var p=!1;return k.filter(function(u){u===g&&(p=!0);return u===f?(p=!1,!0):p})};a.cells({selected:!0}).any()||c?(d=d(c.column,b.column),c=e(c.row,b.row)):(d=d(0,b.column),c=e(0,b.row));c=a.cells(c,d).flatten();a.cells(b,{selected:!0}).any()?a.cells(c).deselect():a.cells(c).select()}function A(a){var b=a.settings()[0]._select.selector;h(a.table().container()).off("mousedown.dtSelect",b).off("mouseup.dtSelect",
b).off("click.dtSelect",b);h("body").off("click.dtSelect"+a.table().node().id.replace(/[^a-zA-Z0-9\-_]/g,"-"))}function F(a){var b=h(a.table().container()),c=a.settings()[0],d=c._select.selector,e;b.on("mousedown.dtSelect",d,function(g){if(g.shiftKey||g.metaKey||g.ctrlKey)b.css("-moz-user-select","none").one("selectstart.dtSelect",d,function(){return!1});q.getSelection&&(e=q.getSelection())}).on("mouseup.dtSelect",d,function(){b.css("-moz-user-select","")}).on("click.dtSelect",d,function(g){var f=
a.select.items();if(e){var k=q.getSelection();if((!k.anchorNode||h(k.anchorNode).closest("table")[0]===a.table().node())&&k!==e)return}k=a.settings()[0];var l=a.settings()[0].oClasses.sWrapper.trim().replace(/ +/g,".");if(h(g.target).closest("div."+l)[0]==a.table().container()&&(l=a.cell(h(g.target).closest("td, th")),l.any())){var p=h.Event("user-select.dt");r(a,p,[f,l,g]);p.isDefaultPrevented()||(p=l.index(),"row"===f?(f=p.row,B(g,a,k,"row",f)):"column"===f?(f=l.index().column,B(g,a,k,"column",
f)):"cell"===f&&(f=l.index(),B(g,a,k,"cell",f)),k._select_lastCell=p)}});h("body").on("click.dtSelect"+a.table().node().id.replace(/[^a-zA-Z0-9\-_]/g,"-"),function(g){!c._select.blurable||h(g.target).parents().filter(a.table().container()).length||0===h(g.target).parents("html").length||h(g.target).parents("div.DTE").length||x(c,!0)})}function r(a,b,c,d){if(!d||a.flatten().length)"string"===typeof b&&(b+=".dt"),c.unshift(a),h(a.table().node()).trigger(b,c)}function I(a){var b=a.settings()[0];if(b._select.info&&
b.aanFeatures.i&&"api"!==a.select.style()){var c=a.rows({selected:!0}).flatten().length,d=a.columns({selected:!0}).flatten().length,e=a.cells({selected:!0}).flatten().length,g=function(f,k,l){f.append(h('<span class="select-item"/>').append(a.i18n("select."+k+"s",{_:"%d "+k+"s selected",0:"",1:"1 "+k+" selected"},l)))};h.each(b.aanFeatures.i,function(f,k){k=h(k);f=h('<span class="select-info"/>');g(f,"row",c);g(f,"column",d);g(f,"cell",e);var l=k.children("span.select-info");l.length&&l.remove();
""!==f.text()&&k.append(f)})}}function J(a){var b=new m.Api(a);a.aoRowCreatedCallback.push({fn:function(c,d,e){d=a.aoData[e];d._select_selected&&h(c).addClass(a._select.className);c=0;for(e=a.aoColumns.length;c<e;c++)(a.aoColumns[c]._select_selected||d._selected_cells&&d._selected_cells[c])&&h(d.anCells[c]).addClass(a._select.className)},sName:"select-deferRender"});b.on("preXhr.dt.dtSelect",function(c,d){if(d===b.settings()[0]){var e=b.rows({selected:!0}).ids(!0).filter(function(f){return f!==n}),
g=b.cells({selected:!0}).eq(0).map(function(f){var k=b.row(f.row).id(!0);return k?{row:k,column:f.column}:n}).filter(function(f){return f!==n});b.one("draw.dt.dtSelect",function(){b.rows(e).select();g.any()&&g.each(function(f){b.cells(f.row,f.column).select()})})}});b.on("draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt",function(){I(b)});b.on("destroy.dtSelect",function(){b.rows({selected:!0}).deselect();A(b);b.off(".dtSelect")})}function G(a,b,c,d){var e=a[b+"s"]({search:"applied"}).indexes();
d=h.inArray(d,e);var g=h.inArray(c,e);if(a[b+"s"]({selected:!0}).any()||-1!==d){if(d>g){var f=g;g=d;d=f}e.splice(g+1,e.length);e.splice(0,d)}else e.splice(h.inArray(c,e)+1,e.length);a[b](c,{selected:!0}).any()?(e.splice(h.inArray(c,e),1),a[b+"s"](e).deselect()):a[b+"s"](e).select()}function x(a,b){if(b||"single"===a._select.style)a=new m.Api(a),a.rows({selected:!0}).deselect(),a.columns({selected:!0}).deselect(),a.cells({selected:!0}).deselect()}function B(a,b,c,d,e){var g=b.select.style(),f=b.select.toggleable(),
k=b[d](e,{selected:!0}).any();if(!k||f)"os"===g?a.ctrlKey||a.metaKey?b[d](e).select(!k):a.shiftKey?"cell"===d?E(b,e,c._select_lastCell||null):G(b,d,e,c._select_lastCell?c._select_lastCell[d]:null):(a=b[d+"s"]({selected:!0}),k&&1===a.flatten().length?b[d](e).deselect():(a.deselect(),b[d](e).select())):"multi+shift"==g?a.shiftKey?"cell"===d?E(b,e,c._select_lastCell||null):G(b,d,e,c._select_lastCell?c._select_lastCell[d]:null):b[d](e).select(!k):b[d](e).select(!k)}function y(a,b){return function(c){return c.i18n("buttons."+
a,b)}}function C(a){a=a._eventNamespace;return"draw.dt.DT"+a+" select.dt.DT"+a+" deselect.dt.DT"+a}function K(a,b){return-1!==h.inArray("rows",b.limitTo)&&a.rows({selected:!0}).any()||-1!==h.inArray("columns",b.limitTo)&&a.columns({selected:!0}).any()||-1!==h.inArray("cells",b.limitTo)&&a.cells({selected:!0}).any()?!0:!1}var m=h.fn.dataTable;m.select={};m.select.version="1.3.3";m.select.init=function(a){var b=a.settings()[0],c=b.oInit.select,d=m.defaults.select;c=c===n?d:c;d="row";var e="api",g=!1,
f=!0,k=!0,l="td, th",p="selected",u=!1;b._select={};!0===c?(e="os",u=!0):"string"===typeof c?(e=c,u=!0):h.isPlainObject(c)&&(c.blurable!==n&&(g=c.blurable),c.toggleable!==n&&(f=c.toggleable),c.info!==n&&(k=c.info),c.items!==n&&(d=c.items),e=c.style!==n?c.style:"os",u=!0,c.selector!==n&&(l=c.selector),c.className!==n&&(p=c.className));a.select.selector(l);a.select.items(d);a.select.style(e);a.select.blurable(g);a.select.toggleable(f);a.select.info(k);b._select.className=p;h.fn.dataTable.ext.order["select-checkbox"]=
function(z,L){return this.api().column(L,{order:"index"}).nodes().map(function(H){return"row"===z._select.items?h(H).parent().hasClass(z._select.className):"cell"===z._select.items?h(H).hasClass(z._select.className):!1})};!u&&h(a.table().node()).hasClass("selectable")&&a.select.style("os")};h.each([{type:"row",prop:"aoData"},{type:"column",prop:"aoColumns"}],function(a,b){m.ext.selector[b.type].push(function(c,d,e){d=d.selected;var g=[];if(!0!==d&&!1!==d)return e;for(var f=0,k=e.length;f<k;f++){var l=
c[b.prop][e[f]];(!0===d&&!0===l._select_selected||!1===d&&!l._select_selected)&&g.push(e[f])}return g})});m.ext.selector.cell.push(function(a,b,c){b=b.selected;var d=[];if(b===n)return c;for(var e=0,g=c.length;e<g;e++){var f=a.aoData[c[e].row];(!0===b&&f._selected_cells&&!0===f._selected_cells[c[e].column]||!(!1!==b||f._selected_cells&&f._selected_cells[c[e].column]))&&d.push(c[e])}return d});var v=m.Api.register,w=m.Api.registerPlural;v("select()",function(){return this.iterator("table",function(a){m.select.init(new m.Api(a))})});
v("select.blurable()",function(a){return a===n?this.context[0]._select.blurable:this.iterator("table",function(b){b._select.blurable=a})});v("select.toggleable()",function(a){return a===n?this.context[0]._select.toggleable:this.iterator("table",function(b){b._select.toggleable=a})});v("select.info()",function(a){return a===n?this.context[0]._select.info:this.iterator("table",function(b){b._select.info=a})});v("select.items()",function(a){return a===n?this.context[0]._select.items:this.iterator("table",
function(b){b._select.items=a;r(new m.Api(b),"selectItems",[a])})});v("select.style()",function(a){return a===n?this.context[0]._select.style:this.iterator("table",function(b){b._select.style=a;b._select_init||J(b);var c=new m.Api(b);A(c);"api"!==a&&F(c);r(new m.Api(b),"selectStyle",[a])})});v("select.selector()",function(a){return a===n?this.context[0]._select.selector:this.iterator("table",function(b){A(new m.Api(b));b._select.selector=a;"api"!==b._select.style&&F(new m.Api(b))})});w("rows().select()",
"row().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("row",function(c,d){x(c);c.aoData[d]._select_selected=!0;h(c.aoData[d].nTr).addClass(c._select.className)});this.iterator("table",function(c,d){r(b,"select",["row",b[d]],!0)});return this});w("columns().select()","column().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("column",function(c,d){x(c);c.aoColumns[d]._select_selected=!0;d=(new m.Api(c)).column(d);h(d.header()).addClass(c._select.className);
h(d.footer()).addClass(c._select.className);d.nodes().to$().addClass(c._select.className)});this.iterator("table",function(c,d){r(b,"select",["column",b[d]],!0)});return this});w("cells().select()","cell().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("cell",function(c,d,e){x(c);d=c.aoData[d];d._selected_cells===n&&(d._selected_cells=[]);d._selected_cells[e]=!0;d.anCells&&h(d.anCells[e]).addClass(c._select.className)});this.iterator("table",function(c,d){r(b,"select",
["cell",b.cells(b[d]).indexes().toArray()],!0)});return this});w("rows().deselect()","row().deselect()",function(){var a=this;this.iterator("row",function(b,c){b.aoData[c]._select_selected=!1;b._select_lastCell=null;h(b.aoData[c].nTr).removeClass(b._select.className)});this.iterator("table",function(b,c){r(a,"deselect",["row",a[c]],!0)});return this});w("columns().deselect()","column().deselect()",function(){var a=this;this.iterator("column",function(b,c){b.aoColumns[c]._select_selected=!1;var d=
new m.Api(b),e=d.column(c);h(e.header()).removeClass(b._select.className);h(e.footer()).removeClass(b._select.className);d.cells(null,c).indexes().each(function(g){var f=b.aoData[g.row],k=f._selected_cells;!f.anCells||k&&k[g.column]||h(f.anCells[g.column]).removeClass(b._select.className)})});this.iterator("table",function(b,c){r(a,"deselect",["column",a[c]],!0)});return this});w("cells().deselect()","cell().deselect()",function(){var a=this;this.iterator("cell",function(b,c,d){c=b.aoData[c];c._selected_cells[d]=
!1;c.anCells&&!b.aoColumns[d]._select_selected&&h(c.anCells[d]).removeClass(b._select.className)});this.iterator("table",function(b,c){r(a,"deselect",["cell",a[c]],!0)});return this});var D=0;h.extend(m.ext.buttons,{selected:{text:y("selected","Selected"),className:"buttons-selected",limitTo:["rows","columns","cells"],init:function(a,b,c){var d=this;c._eventNamespace=".select"+D++;a.on(C(c),function(){d.enable(K(a,c))});this.disable()},destroy:function(a,b,c){a.off(c._eventNamespace)}},selectedSingle:{text:y("selectedSingle",
"Selected single"),className:"buttons-selected-single",init:function(a,b,c){var d=this;c._eventNamespace=".select"+D++;a.on(C(c),function(){var e=a.rows({selected:!0}).flatten().length+a.columns({selected:!0}).flatten().length+a.cells({selected:!0}).flatten().length;d.enable(1===e)});this.disable()},destroy:function(a,b,c){a.off(c._eventNamespace)}},selectAll:{text:y("selectAll","Select all"),className:"buttons-select-all",action:function(){this[this.select.items()+"s"]().select()}},selectNone:{text:y("selectNone",
"Deselect all"),className:"buttons-select-none",action:function(){x(this.settings()[0],!0)},init:function(a,b,c){var d=this;c._eventNamespace=".select"+D++;a.on(C(c),function(){var e=a.rows({selected:!0}).flatten().length+a.columns({selected:!0}).flatten().length+a.cells({selected:!0}).flatten().length;d.enable(0<e)});this.disable()},destroy:function(a,b,c){a.off(c._eventNamespace)}}});h.each(["Row","Column","Cell"],function(a,b){var c=b.toLowerCase();m.ext.buttons["select"+b+"s"]={text:y("select"+
b+"s","Select "+c+"s"),className:"buttons-select-"+c+"s",action:function(){this.select.items(c)},init:function(d){var e=this;d.on("selectItems.dt.DT",function(g,f,k){e.active(k===c)})}}});h(t).on("preInit.dt.dtSelect",function(a,b){"dt"===a.namespace&&m.select.init(new m.Api(b))});return m.select});

View File

@@ -1,6 +1,6 @@
<?php
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# maintenance.php - Front module. Server side. Maintenance #
@@ -57,7 +57,7 @@ $pia_installed_skins = array('skin-black-light',
// Size and last mod of DB ------------------------------------------------------
$pia_db = str_replace('front', 'db', getcwd()).'/pialert.db';
$pia_db = str_replace('front', 'db', getcwd()).'/app.db';
$pia_db_size = number_format((filesize($pia_db) / 1000000),2,",",".") . ' MB';
$pia_db_mod = date ("F d Y H:i:s", filemtime($pia_db));
@@ -67,7 +67,7 @@ $pia_db_mod = date ("F d Y H:i:s", filemtime($pia_db));
$Pia_Archive_Path = str_replace('front', 'db', getcwd()).'/';
$Pia_Archive_count = 0;
$Pia_Archive_diskusage = 0;
$files = glob($Pia_Archive_Path."pialertdb_*.zip");
$files = glob($Pia_Archive_Path."appdb_*.zip");
if ($files){
$Pia_Archive_count = count($files);
}
@@ -78,7 +78,7 @@ $Pia_Archive_diskusage = number_format(($Pia_Archive_diskusage / 1000000),2,",",
// Find latest Backup for restore -----------------------------------------------
$latestfiles = glob($Pia_Archive_Path."pialertdb_*.zip");
$latestfiles = glob($Pia_Archive_Path."appdb_*.zip");
natsort($latestfiles);
$latestfiles = array_reverse($latestfiles,False);
@@ -161,7 +161,7 @@ $db->close();
<div class="db_info_table">
<div class="db_info_table_row">
<div class="db_info_table_cell" style="min-width: 140px"><?= lang('Maintenance_version');?>
<a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/VERSIONS.md" target="_blank"> <span><i class="fa fa-circle-question"></i></a><span>
<a href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/VERSIONS.md" target="_blank"> <span><i class="fa fa-circle-question"></i></a><span>
</div>
<div class="db_info_table_cell">
@@ -243,6 +243,12 @@ $db->close();
<?= lang('Maintenance_Tools_Tab_Logging');?>
</a>
</li>
<li>
<a id="tab_multiEdit_id" href="#tab_multiEdit" data-toggle="tab">
<i class="fa fa-pencil pointer" ></i>
<?= lang('Device_MultiEdit');?>
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_Settings">
@@ -397,14 +403,14 @@ $db->close();
<div class="db_info_table">
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="pialert_log" class="logs" cols="70" rows="10" wrap='off' readonly >
<textarea id="app_log" class="logs" cols="70" rows="10" wrap='off' readonly >
<?php
if(filesize("./log/pialert.log") > 2000000)
if(filesize("./log/app.log") > 2000000)
{
echo file_get_contents( "./log/pialert.log", false, null, -2000000);
echo file_get_contents( "./log/app.log", false, null, -2000000);
}
else{
echo file_get_contents( "./log/pialert.log" );
echo file_get_contents( "./log/app.log" );
}
?>
@@ -412,43 +418,43 @@ $db->close();
</div>
<div class="row logs-row" >
<div>
<div class="log-file">pialert.log <div class="logs-size"><?php echo number_format((filesize("./log/pialert.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/pialert.log" target="_blank"><i class="fa fa-download"></i> </a></span>
<div class="log-file">app.log <div class="logs-size"><?php echo number_format((filesize("./log/app.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app.log" target="_blank"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('pialert.log','cleanLog')"><?= lang('Gen_Purge');?></button>
<button class="btn btn-primary" onclick="logManage('app.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="pialert_front_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/pialert_front.log" ); ?>
<textarea id="app_front_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/app_front.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">pialert_front.log<div class="logs-size"><?php echo number_format((filesize("./log/pialert_front.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/pialert_front.log"><i class="fa fa-download"></i> </a></span>
<div class="log-file">app_front.log<div class="logs-size"><?php echo number_format((filesize("./log/app_front.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app_front.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('pialert_front.log','cleanLog')"><?= lang('Gen_Purge');?></button>
<button class="btn btn-primary" onclick="logManage('app_front.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
</div>
<div class="log-area box box-solid box-primary">
<div class="row logs-row">
<textarea id="pialert_php_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/pialert.php_errors.log" ); ?>
<textarea id="app_php_log" class="logs" cols="70" rows="10" wrap='off' readonly><?php echo file_get_contents( "./log/app.php_errors.log" ); ?>
</textarea>
</div>
<div class="row logs-row" >
<div>
<div class="log-file">pialert.php_errors.log<div class="logs-size"><?php echo number_format((filesize("./log/pialert.php_errors.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/pialert.php_errors.log"><i class="fa fa-download"></i> </a></span>
<div class="log-file">app.php_errors.log<div class="logs-size"><?php echo number_format((filesize("./log/app.php_errors.log") / 1000000),2,",",".") . ' MB';?>
<span class="span-padding"><a href="./log/app.php_errors.log"><i class="fa fa-download"></i> </a></span>
</div></div>
<div class="log-purge">
<button class="btn btn-primary" onclick="logManage('pialert.php_errors.log','cleanLog')"><?= lang('Gen_Purge');?></button>
<button class="btn btn-primary" onclick="logManage('app.php_errors.log','cleanLog')"><?= lang('Gen_Purge');?></button>
</div>
</div>
</div>
@@ -501,8 +507,21 @@ $db->close();
</div>
</div>
<!-- ---------------------------Bulk edit -------------------------------------------- -->
<div class="tab-pane" id="tab_multiEdit">
<div class="db_info_table">
<div class="box box-solid">
<?php
require 'multiEditCore.php';
?>
</div>
</div>
</div>
</div>
<!-- ------------------------------------------------------------------------------ -->
</div>
<div class="box-body" style="text-align: center;">
@@ -763,20 +782,34 @@ function performLogManage() {
}
// --------------------------------------------------------
// scroll down the log areas
function scrollDown()
{
var areaIDs = ['pialert_log', 'pialert_front_log', 'IP_changes_log', 'stdout_log', 'stderr_log', 'pialert_pholus_log', 'pialert_pholus_lastrun_log', 'pialert_php_log'];
for (let i = 0; i < areaIDs.length; i++) {
setTimeout(() => {
var tempArea = $('#' + areaIDs[i]);
if (tempArea.length > 0)
var elementToCheck = $("#tab_Logging_id");
// Check if the parent <li> is active
if (elementToCheck.parent().hasClass("active")) {
{
$(tempArea[0]).scrollTop(tempArea[0].scrollHeight);
}
var areaIDs = ['app_log', 'app_front_log', 'IP_changes_log', 'stdout_log', 'stderr_log', 'app_pholus_log', 'app_pholus_lastrun_log', 'app_php_log'];
for (let i = 0; i < areaIDs.length; i++) {
}
var tempArea = $('#' + areaIDs[i]);
if (tempArea.length > 0)
{
$(tempArea[0]).scrollTop(tempArea[0].scrollHeight);
}
}
}
}
}, 200);
}
// --------------------------------------------------------
@@ -827,37 +860,12 @@ function initializeSelectedColumns () {
$("#columnsSelect").append(option).trigger('change');
$(option).attr('eee','eee')
}
});
}
// --------------------------------------------------------
//Initialize Select2 Elements and make them sortable
$(function () {
var selectEl = $('.select2').select2();
selectEl.next().children().children().children().sortable({
containment: 'parent',
update: function () {
var sortedValues = $(this).children().map(function() {
return $(this).attr('title');
}).get();
var sortedOptions = selectEl.find('option').sort(function(a, b) {
return sortedValues.indexOf($(a).text()) - sortedValues.indexOf($(b).text());
});
// Replace all options in selectEl
selectEl.empty().append(sortedOptions);
// Trigger change event on Select2
selectEl.trigger('change');
}
});
});
// --------------------------------------------------------
@@ -865,72 +873,79 @@ $(function () {
// --------------------------------------------------------
function initializeTabs () {
key = "activeMaintenanceTab"
setTimeout(function() {
// default selection
selectedTab = "tab_Settings"
key = "activeMaintenanceTab"
// the #target from the url
target = window.location.hash.substr(1)
// default selection
selectedTab = "tab_Settings"
// update cookie if target specified
if(target != "")
{
setCache(key, target+'_id') // _id is added so it doesn't conflict with AdminLTE tab behavior
}
// the #target from the url
target = window.location.hash.substr(1)
// get the tab id from the cookie (already overriden by the target)
if(!emptyArr.includes(getCache(key)))
{
selectedTab = getCache(key);
}
// Activate panel
$('.nav-tabs a[id='+ selectedTab +']').tab('show');
// When changed save new current tab
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
setCache(key, $(e.target).attr('id'))
});
// events on tab change
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href") // activated tab
if(target == "#tab_Logging")
// get only the part between #...?
if(target.includes('?'))
{
scrollDown();
target = target.split('?')[0]
}
});
console.log(target);
// update cookie if target specified
if(target != "")
{
if (!selectedTab.endsWith("_id")) {
selectedTab = target + "_id";
}
setCache(key, selectedTab) // _id is added so it doesn't conflict with AdminLTE tab behavior
}
// get the tab id from the cookie (already overriden by the target)
if(!emptyArr.includes(getCache(key)))
{
selectedTab = getCache(key);
}
// Activate panel
$('.nav-tabs a[id='+ selectedTab +']').tab('show');
// When changed save new current tab
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
setCache(key, $(e.target).attr('id'))
});
// events on tab change
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href") // activated tab
});
}, 50);
}
// --------------------------------------------------------
// save language in a cookie
$('#langselector').on('change', function (e) {
var optionSelected = $("option:selected", this);
var valueSelected = this.value;
setCookie("language",valueSelected )
location.reload();
});
// --------------------------------------------------------
// load footer asynchronously not to block the page load/other sections
window.onload = function asyncFooter()
{
initializeSelectedColumns();
scrollDown();
initializeTabs();
$("#lastCommit").append('<a href="https://github.com/jokob-sk/Pi.Alert/commits" target="_blank"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jokob-sk/pi.alert/main?logo=github"></a>');
$("#lastCommit").append('<a href="https://github.com/jokob-sk/NetAlertX/commits" target="_blank"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jokob-sk/netalertx/main?logo=github"></a>');
$("#lastDockerUpdate").append(
'<a href="https://hub.docker.com/r/jokobsk/pi.alert/tags" target="_blank"><img alt="Docker last pushed" src="https://img.shields.io/badge/dynamic/json?color=blue&label=Last%20pushed&query=last_updated&url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fjokobsk%2Fpi.alert%2F&logo=docker&?link=http://left&link=https://hub.docker.com/repository/docker/jokobsk/pi.alert"></a>');
'<a href="https://github.com/jokob-sk/NetAlertX/releases" target="_blank"><img alt="Docker last pushed" src="https://img.shields.io/github/v/release/jokob-sk/NetAlertX?color=0aa8d2&logoColor=fff&logo=GitHub&label=Latest"></a>');
}
// scroll to the latest log entrie sat teh bottom of the file
</script>
<link rel="stylesheet" href="lib/AdminLTE/bower_components/select2/dist/css/select2.min.css">
@@ -938,6 +953,3 @@ window.onload = function asyncFooter()
<script src="lib/AdminLTE/bower_components/jquery-ui/jquery-ui.min.js"></script>
<!-- ----------------------------------------------------------------------- -->
<script src="js/pialert_common.js"></script>

286
front/multiEditCore.php Executable file
View File

@@ -0,0 +1,286 @@
<div class="col-md-12">
<div class="box box-default">
<div class="box-header">
<h3 class="box-title"><?= lang('Gen_Selected_Devices');?></h3>
</div>
<div class="deviceSelector"></div>
<div class="callout callout-warning">
<h4><?= lang('Gen_Warning');?></h4>
<p><?= lang('Device_MultiEdit_Backup');?></p>
</div>
</div>
<div class="col-md-12">
<div class="box box-default">
<div class="box-header">
<h3 class="box-title"><?= lang('Device_MultiEdit_Fields');?></h3>
</div>
<div class="box-body">
<form id="multi-edit-form">
<!-- Form fields will be appended here -->
</form>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div class="box box-default">
<div class="box-header ">
<h3 class="box-title"><?= lang('Device_MultiEdit_MassActions');?></h3>
</div>
<div class="box-body">
<div class="col-md-2" style="">
<button type="button" class="btn btn-default pa-btn pa-btn-delete bg-red" id="btnDeleteMAC" onclick="askDeleteSelectedDevices()"><?= lang('Maintenance_Tool_del_selecteddev');?></button>
</div>
<div class="col-md-10"><?= lang('Maintenance_Tool_del_selecteddev_text');?></div>
</div>
</div>
</div>
</div>
<script defer>
// -------------------------------------------------------------------
// Get plugin and settings data from API endpoints
function getData(){
$.get('api/table_settings.json?nocache=' + Date.now(), function(res) {
settingsData = res["data"];
excludedColumns = ["NEWDEV_dev_MAC", "NEWDEV_dev_FirstConnection", "NEWDEV_dev_LastConnection", "NEWDEV_dev_LastNotification", "NEWDEV_dev_LastIP", "NEWDEV_dev_StaticIP", "NEWDEV_dev_ScanCycle", "NEWDEV_dev_PresentLastScan" ]
const relevantColumns = settingsData.filter(set =>
set.Group === "NEWDEV" &&
set.Code_Name.includes("_dev_") &&
!excludedColumns.includes(set.Code_Name) &&
!set.Code_Name.includes("__metadata")
);
const generateSimpleForm = columns => {
const form = $('#multi-edit-form');
const numColumns = 2; // Number of columns
// Calculate number of elements per column
const elementsPerColumn = Math.ceil(columns.length / numColumns);
// Divide columns equally
for (let i = 0; i < numColumns; i++) {
const column = $('<div>').addClass('col-md-6');
// Append form groups to the column
for (let j = i * elementsPerColumn; j < Math.min((i + 1) * elementsPerColumn, columns.length); j++) {
let inputType;
switch (columns[j].Type) {
case 'integer.checkbox':
case 'checkbox':
inputType = 'checkbox';
break;
case 'text.select':
inputType = 'text.select';
break;
default:
inputType = 'text';
break;
}
if (inputType === 'text.select') {
targetLocation = columns[j].Code_Name + "_initSettingDropdown"
initSettingDropdown(columns[j].Code_Name, [], targetLocation, generateDropdownOptions)
// Handle Icons as tehy need a preview
if(columns[j].Code_Name == 'NEWDEV_dev_Icon')
{
input = `
<span class="input-group-addon" id="txtIconFA"></span>
<select class="form-control"
onChange="updateIconPreview('#NEWDEV_dev_Icon')"
id="${columns[j].Code_Name}"
data-my-column="${columns[j].Code_Name}"
data-my-targetColumns="${columns[j].Code_Name.replace('NEWDEV_','')}" >
<option id="${targetLocation}"></option>
</select>`
} else{
input = `<select class="form-control"
id="${columns[j].Code_Name}"
data-my-column="${columns[j].Code_Name}"
data-my-targetColumns="${columns[j].Code_Name.replace('NEWDEV_','')}" >
<option id="${targetLocation}"></option>
</select>`
}
} else {
// Add classes specifically for checkboxes
if (inputType === 'checkbox') {
inputClass = 'checkbox';
} else {
inputClass = 'form-control';
}
input = `<input class="${inputClass}"
id="${columns[j].Code_Name}"
data-my-column="${columns[j].Code_Name}"
data-my-targetColumns="${columns[j].Code_Name.replace('NEWDEV_','')}"
type="${inputType}">`
}
const inputEntry = `<div class="form-group col-sm-12" >
<label class="col-sm-3 control-label">${columns[j].Display_Name}</label>
<div class="col-sm-9">
<div class="input-group red-hover-border">
${input}
<span class="input-group-addon pointer red-hover-background" onclick="massUpdateField('${columns[j].Code_Name}');" title="${getString('Device_MultiEdit_Tooltip')}">
<i class="fa fa-save"></i>
</span>
</div>
</div>
</div>`
column.append(inputEntry);
}
form.append(column);
}
};
console.log(relevantColumns)
generateSimpleForm(relevantColumns);
})
}
// -----------------------------------------------------------------------------
// Get selected devices Macs
function selectorMacs () {
return $('.deviceSelector select').val().join(',');
}
// -----------------------------------------------------------------------------
// Update specified field over the specified DB column and selected entry(ies)
function massUpdateField(id) {
// Get the input element
var inputElement = $(`#${id}`);
console.log(inputElement);
console.log(id);
// Initialize columnValue variable
var columnValue;
// Check the type of the input element
if (inputElement.is(':checkbox')) {
// For checkboxes, set the value to 1 if checked, otherwise set it to 0
columnValue = inputElement.is(':checked') ? 1 : 0;
} else {
// For other input types (like textboxes), simply retrieve their values
columnValue = inputElement.val();
}
var targetColumns = inputElement.attr('data-my-targetColumns');
console.log(targetColumns);
console.log(columnValue);
// update selected
executeAction('update', 'dev_MAC', selectorMacs(), targetColumns, columnValue )
}
// -----------------------------------------------------------------------------
// action: Represents the action to be performed, a CRUD operation like "update", "delete", etc.
// whereColumnName: Specifies the name of the column used in the WHERE or SELECT statement for filtering.
// key: Represents the unique identifier of the row or record to be acted upon.
// targetColumns: Indicates the columns to be updated or affected by the action.
// newTargetColumnValue: Specifies the new value to be assigned to the specified column(s).
function executeAction(action, whereColumnName, key, targetColumns, newTargetColumnValue )
{
$.get(`php/server/dbHelper.php?action=${action}&dbtable=Devices&columnName=${whereColumnName}&id=${key}&columns=${targetColumns}&values=${newTargetColumnValue}`, function(data) {
// console.log(data);
if (sanitize(data) == 'OK') {
showMessage(getString('Gen_DataUpdatedUITakesTime'));
// Remove navigation prompt "Are you sure you want to leave..."
window.onbeforeunload = null;
// update API endpoints to refresh the UI
updateApi()
} else {
showMessage(getString('Gen_LockedDB'));
}
});
}
// -----------------------------------------------------------------------------
// Ask to delete selected devices
function askDeleteSelectedDevices () {
// Ask
showModalWarning(
getString('Maintenance_Tool_del_alldev_noti'),
getString('Gen_AreYouSure'),
getString('Gen_Cancel'),
getString('Gen_Delete'),
'deleteSelectedDevices');
}
// -----------------------------------------------------------------------------
// Delete selected devices
function deleteSelectedDevices()
{
executeAction('delete', 'dev_MAC', selectorMacs() )
}
getData();
</script>
<!-- ----------------------------------------------------------------------- -->
<script src="js/ui_components.js"></script>
<script src="js/db_methods.js"></script>
<!-- ----------------------------------------------------------------------- -->

View File

@@ -18,7 +18,7 @@
<?php require 'php/templates/notification.php'; ?>
<h1 id="pageTitle">
<i class="fa fa-network-wired"></i> <?= lang('Network_Title');?>
<span class="networkPageHelp"> <a target="_blank" href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/NETWORK_TREE.md"><i class="fa fa-circle-question"></i></a><span>
<span class="networkPageHelp"> <a target="_blank" href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md"><i class="fa fa-circle-question"></i></a><span>
</h1>
</section>
@@ -26,7 +26,7 @@
<div id="networkTree" class="drag"></div>
<!-- Main content ---------------------------------------------------------- -->
<section class="content">
<section class="content networkTable">
<?php
// Create top-level node (network devices) tabs
function createDeviceTabs($node_mac, $node_name, $node_status, $node_type, $node_ports_count, $icon, $activetab) {
@@ -47,15 +47,12 @@
$node_badge = circle_offline;
}
if($icon != '')
{
$icon = '<i class="fa fa-'.$icon.'"></i> ';
}
$decoded_icon = base64_decode($icon);
$idFromMac = str_replace(":", "_", $node_mac);
$str_tab_header = '<li class="'.$activetab.'">
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" >' // _id is added so it doesn't conflict with AdminLTE tab behavior
.$icon.$node_name.' ' .$str_port.$node_badge.
.'<div class="icon">'.$decoded_icon.' </div>'.$node_name.' ' .$str_port.$node_badge.
'</a>
</li>';
@@ -454,7 +451,7 @@
<script src="lib/treeviz/index.js"></script>
<script src="lib/treeviz/require.js"></script>
<script src="js/pialert_common.js"></script>
<script>
$.get('php/server/devices.php?action=getDevicesList&status=all&forceDefaultOrder', function(data) {
@@ -660,7 +657,7 @@
// Build HTML for individual nodes in the network diagram
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
`<div class="netIcon">
<i class="fa fa-${nodeData.data.icon}"></i>
${atob(nodeData.data.icon)}
</div>` : "";
devicePort = `<div class="netPort"
style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em">
@@ -724,6 +721,9 @@
console.log(myHierarchy)
myTree.refresh(myHierarchy);
// hide spinning icon
hideSpinner()
}
// ---------------------------------------------------------------------------
@@ -840,6 +840,8 @@
}
}
// show spinning icon
showSpinner()
// init device names where macs are used
initDeviceNamesFromMACs();

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// db.php - Front module. Server side. DB common file
@@ -10,7 +10,7 @@
//------------------------------------------------------------------------------
// DB File Path
$DBFILE = dirname(__FILE__).'/../../../db/pialert.db';
$DBFILE = dirname(__FILE__).'/../../../db/app.db';
//------------------------------------------------------------------------------
// Connect DB

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// parameters.php - Front module. Server side. Manage Parameters
@@ -56,6 +56,10 @@
$columns = $_REQUEST['columns'];
}
if (isset ($_REQUEST['rawSql'])) {
$rawSql = $_REQUEST['rawSql'];
}
if (isset ($_REQUEST['dbtable'])) {
$dbtable = $_REQUEST['dbtable'];
}
@@ -64,92 +68,148 @@
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action'];
switch ($action) {
case 'create': create($skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values ); break;
// case 'read' : read($skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values); break;
case 'update': update($columnName, $id, $skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values); break;
case 'create': create($defaultValue, $expireMinutes, $dbtable, $columns, $values ); break;
case 'read' : read($rawSql); break;
case 'update': update($columnName, $id, $defaultValue, $expireMinutes, $dbtable, $columns, $values); break;
case 'delete': delete($columnName, $id, $dbtable); break;
default: logServerConsole ('Action: '. $action); break;
}
}
//------------------------------------------------------------------------------
// read
//------------------------------------------------------------------------------
function read($rawSql) {
global $db;
// Construct the SQL query to select values
$sql = $rawSql;
// Execute the SQL query
$result = $db->query($sql);
// Check if the query executed successfully
if (! $result == TRUE) {
// Output an error message if the query failed
echo "Error reading data\n\n " .$sql." \n\n". $db->lastErrorMsg();
return;
} else
{
// Output $result
// Fetching rows from the result object and storing them in an array
$rows = array();
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$rows[] = $row;
}
// Converting the array to JSON
$json = json_encode($rows);
// Outputting the JSON
echo $json;
return;
}
}
//------------------------------------------------------------------------------
// update
//------------------------------------------------------------------------------
function update($columnName, $id, $skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values) {
function update($columnName, $id, $defaultValue, $expireMinutes, $dbtable, $columns, $values) {
global $db;
// handle one or multiple columns
if(strpos($columns, ',') !== false)
{
$columnsArr = explode(",", $columns);
}else
{
$columnsArr = array($columns);
// Handle one or multiple columns
if(strpos($columns, ',') !== false) {
$columnsArr = explode(",", $columns);
} else {
$columnsArr = array($columns);
}
// handle one or multiple values
if(strpos($values, ',') !== false)
{
$valuesArr = explode(",", $values);
} else
{
$valuesArr = array($values);
// Handle one or multiple values
if(strpos($values, ',') !== false) {
$valuesArr = explode(",", $values);
} else {
$valuesArr = array($values);
}
// Handle one or multiple IDs
if(strpos($id, ',') !== false) {
$idsArr = explode(",", $id);
$idsPlaceholder = rtrim(str_repeat('?,', count($idsArr)), ',');
} else {
$idsArr = array($id);
$idsPlaceholder = '?';
}
// Build column-value pairs string
$columnValues = '';
$index = 0;
foreach($columnsArr as $column)
{
$columnValues = $columnValues .' "' .$column.'" = "'.$valuesArr[$index] . '",' ;
$index = $index + 1;
foreach($columnsArr as $column) {
$columnValues .= '"' . $column . '" = ?,';
}
// Remove trailing comma
$columnValues = rtrim($columnValues, ',');
// Construct the SQL query
$sql = 'UPDATE ' . $dbtable . ' SET ' . $columnValues . ' WHERE ' . $columnName . ' IN (' . $idsPlaceholder . ')';
$columnValues = substr($columnValues, 0, -1);
// Update value
$sql = 'UPDATE '.$dbtable.' SET '. $columnValues .'
WHERE "'. $columnName .'"="'. $id.'"';
$result = $db->query($sql);
// Prepare the statement
$stmt = $db->prepare($sql);
if (! $result == TRUE) {
echo "Error updating parameter\n\n$sql \n\n". $db->lastErrorMsg();
return;
// Check for errors
if(!$stmt) {
echo "Error preparing statement: " . $db->lastErrorMsg();
return;
}
// Bind the parameters
$paramTypes = str_repeat('s', count($columnsArr));
foreach($valuesArr as $i => $value) {
$stmt->bindValue($i + 1, $value);
}
foreach($idsArr as $i => $idValue) {
$stmt->bindValue(count($valuesArr) + $i + 1, $idValue);
}
// Execute the statement
$result = $stmt->execute();
$changes = $db->changes();
if ($changes == 0) {
// Insert new value
create($skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values);
create( $defaultValue, $expireMinutes, $dbtable, $columns, $values);
}
// update cache
$uniqueHash = hash('ripemd160', $dbtable . $columns);
setCache($uniqueHash, $values, $expireMinutes);
echo 'OK';
echo 'OK' ;
}
//------------------------------------------------------------------------------
// create
//------------------------------------------------------------------------------
function create($skipCache, $defaultValue, $expireMinutes, $dbtable, $columns, $values)
function create( $defaultValue, $expireMinutes, $dbtable, $columns, $values)
{
global $db;
// Insert new value
$sql = 'INSERT INTO '.$dbtable.' ('.$columns.')
VALUES ("'. quotes($parameter) .'",
"'. $values .'")';
$result = $db->query($sql);
echo "NOT IMPLEMENTED!\n\n";
return;
if (! $result == TRUE) {
echo "Error creating entry\n\n$sql \n\n". $db->lastErrorMsg();
return;
}
// // Insert new value
// $sql = 'INSERT INTO '.$dbtable.' ('.$columns.')
// VALUES ("'. quotes($parameter) .'",
// "'. $values .'")';
// $result = $db->query($sql);
// if (! $result == TRUE) {
// echo "Error creating entry\n\n$sql \n\n". $db->lastErrorMsg();
// return;
// }
}
//------------------------------------------------------------------------------
@@ -159,35 +219,49 @@ function delete($columnName, $id, $dbtable)
{
global $db;
// handle one or multiple ids
// Handle one or multiple ids
if(strpos($id, ',') !== false)
{
$idsArr = explode(",", $id);
}else
} else
{
$idsArr = array($id);
}
// Initialize an empty string to store the comma-separated list of IDs
$idsStr = "";
foreach ($idsArr as $item)
// Iterate over each ID
foreach ($idsArr as $index => $item)
{
$idsStr = $idsStr . '"' .$item.'"';
// Append the current ID to the string
$idsStr .= '"' . $item . '"';
// Add a comma if the current ID is not the last one
if ($index < count($idsArr) - 1) {
$idsStr .= ', ';
}
}
// Insert new value
// Construct the SQL query to delete entries based on the given IDs
$sql = 'DELETE FROM '.$dbtable.' WHERE "'.$columnName.'" IN ('. $idsStr .')';
// Execute the SQL query
$result = $db->query($sql);
// Check if the query executed successfully
if (! $result == TRUE) {
echo "Error deleting entry\n\n$sql \n\n". $db->lastErrorMsg();
// Output an error message if the query failed
echo "Error deleting entry\n\n".$sql." \n\n". $db->lastErrorMsg();
return;
} else
{
echo lang('Gen_DataUpdatedUITakesTime');
// Output 'OK' if the deletion was successful
echo 'OK' ;
return;
}
}
?>

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// devices.php - Front module. Server side. Manage Devices
@@ -24,7 +24,6 @@
switch ($action) {
case 'getDeviceData': getDeviceData(); break;
case 'setDeviceData': setDeviceData(); break;
case 'getNetworkNodes': getNetworkNodes(); break;
case 'deleteDevice': deleteDevice(); break;
case 'deleteAllWithEmptyMACs': deleteAllWithEmptyMACs(); break;
case 'createBackupDB': createBackupDB(); break;
@@ -47,10 +46,6 @@
case 'getDevicesList': getDevicesList(); break;
case 'getDevicesListCalendar': getDevicesListCalendar(); break;
case 'getOwners': getOwners(); break;
case 'getDeviceTypes': getDeviceTypes(); break;
case 'getGroups': getGroups(); break;
case 'getLocations': getLocations(); break;
case 'updateNetworkLeaf': updateNetworkLeaf(); break;
case 'overwriteIconType': overwriteIconType(); break;
case 'getIcons': getIcons(); break;
@@ -336,24 +331,25 @@ function deleteActHistory() {
//------------------------------------------------------------------------------
function PiaBackupDBtoArchive() {
// prepare fast Backup
$file = '../../../db/pialert.db';
$newfile = '../../../db/pialert.db.latestbackup';
$dbfilename = 'app.db';
$file = '../../../db/'.$dbfilename;
$newfile = '../../../db/'.$dbfilename.'.latestbackup';
// copy files as a fast Backup
if (!copy($file, $newfile)) {
echo lang('BackDevices_Backup_CopError');
} else {
// Create archive with actual date
$Pia_Archive_Name = 'pialertdb_'.date("Ymd_His").'.zip';
$Pia_Archive_Name = 'appdb_'.date("Ymd_His").'.zip';
$Pia_Archive_Path = '../../../db/';
exec('zip -j '.$Pia_Archive_Path.$Pia_Archive_Name.' ../../../db/pialert.db', $output);
exec('zip -j '.$Pia_Archive_Path.$Pia_Archive_Name.' ../../../db/'.$dbfilename, $output);
// chheck if archive exists
if (file_exists($Pia_Archive_Path.$Pia_Archive_Name) && filesize($Pia_Archive_Path.$Pia_Archive_Name) > 0) {
echo lang('BackDevices_Backup_okay').': ('.$Pia_Archive_Name.')';
unlink($newfile);
echo("<meta http-equiv='refresh' content='1'>");
} else {
echo lang('BackDevices_Backup_Failed').' (pialert.db.latestbackup)';
echo lang('BackDevices_Backup_Failed').' ('.$dbfilename.'.latestbackup)';
}
}
@@ -364,17 +360,17 @@ function PiaBackupDBtoArchive() {
//------------------------------------------------------------------------------
function PiaRestoreDBfromArchive() {
// prepare fast Backup
$file = '../../../db/pialert.db';
$oldfile = '../../../db/pialert.db.prerestore';
$file = '../../../db/'.$dbfilename;
$oldfile = '../../../db/'.$dbfilename.'.prerestore';
// copy files as a fast Backup
if (!copy($file, $oldfile)) {
echo lang('BackDevices_Restore_CopError');
} else {
// extract latest archive and overwrite the actual pialert.db
// extract latest archive and overwrite the actual .db
$Pia_Archive_Path = '../../../db/';
exec('/bin/ls -Art '.$Pia_Archive_Path.'*.zip | /bin/tail -n 1 | /usr/bin/xargs -n1 /bin/unzip -o -d ../../../db/', $output);
// check if the pialert.db exists
// check if the .db exists
if (file_exists($file)) {
echo lang('BackDevices_Restore_okay');
unlink($oldfile);
@@ -393,7 +389,7 @@ function PiaPurgeDBBackups() {
$Pia_Archive_Path = '../../../db';
$Pia_Backupfiles = array();
$files = array_diff(scandir($Pia_Archive_Path, SCANDIR_SORT_DESCENDING), array('.', '..', 'pialert.db', 'pialertdb-reset.zip'));
$files = array_diff(scandir($Pia_Archive_Path, SCANDIR_SORT_DESCENDING), array('.', '..', $dbfilename, 'netalertxdb-reset.zip'));
foreach ($files as &$item)
{
@@ -650,7 +646,7 @@ function getDevicesList() {
$row['dev_Name'],
$row['dev_Owner'],
handleNull($row['dev_DeviceType']),
handleNull($row['dev_Icon'], "laptop"),
handleNull($row['dev_Icon'], "PGkgY2xhc3M9J2ZhIGZhLWxhcHRvcCc+PC9pPg=="), // laptop icon
$row['dev_Favorite'],
$row['dev_Group'],
// ----
@@ -743,71 +739,9 @@ function getDevicesListCalendar() {
}
//------------------------------------------------------------------------------
// Query the List of Owners
//------------------------------------------------------------------------------
function getOwners() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 1 as dev_Order, dev_Owner
FROM Devices
WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
AND dev_Favorite = 1
UNION
SELECT DISTINCT 2 as dev_Order, dev_Owner
FROM Devices
WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
AND dev_Favorite = 0
AND dev_Owner NOT IN
(SELECT dev_Owner FROM Devices WHERE dev_Favorite = 1)
ORDER BY 1,2 ';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Owner']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query Device Data
//------------------------------------------------------------------------------
function getNetworkNodes() {
global $db;
// Device Data
$networkDeviceTypes = str_replace("]", "",(str_replace("[", "", getSettingValue("NETWORK_DEVICE_TYPES"))));
$sql = 'SELECT * FROM Devices WHERE dev_DeviceType in ( '. $networkDeviceTypes .' )';
// echo $sql;
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
// Push row data
$tableData[] = array('id' => $row['dev_MAC'],
'name' => $row['dev_Name'] );
}
// Control no rows
if (empty($tableData)) {
$tableData = [];
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
function getIcons() {
@@ -821,10 +755,10 @@ function getIcons() {
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$icon = handleNull($row['dev_Icon'], "laptop");
$icon = handleNull($row['dev_Icon'], "<i class='fa fa-laptop'></i>");
// Push row data
$tableData[] = array('id' => $icon,
'name' => '<i class="fa fa-'.$icon.'"></i> - '.$icon );
'name' => $icon );
}
// Control no rows
@@ -878,157 +812,6 @@ function getDevices() {
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of types
//------------------------------------------------------------------------------
function getDeviceTypes() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 9 as dev_Order, dev_DeviceType
FROM Devices
WHERE dev_DeviceType NOT IN ("",
"Smartphone", "Tablet",
"Laptop", "Mini PC", "PC", "Printer", "Server", "Singleboard Computer (SBC)", "NAS",
"Domotic", "IP Camera", "Game Console", "SmartTV", "TV Decoder", "Virtual Assistance",
"Clock", "House Appliance", "Phone", "Radio",
"AP", "Gateway", "Firewall", "Hypervisor", "Powerline", "Switch", "WLAN", "PLC", "Router","USB LAN Adapter", "USB WIFI Adapter" )
UNION SELECT 1 as dev_Order, "Smartphone"
UNION SELECT 1 as dev_Order, "Tablet"
UNION SELECT 2 as dev_Order, "Laptop"
UNION SELECT 2 as dev_Order, "Mini PC"
UNION SELECT 2 as dev_Order, "PC"
UNION SELECT 2 as dev_Order, "Printer"
UNION SELECT 2 as dev_Order, "Server"
UNION SELECT 2 as dev_Order, "Singleboard Computer (SBC)"
UNION SELECT 2 as dev_Order, "NAS"
UNION SELECT 3 as dev_Order, "Domotic"
UNION SELECT 3 as dev_Order, "IP Camera"
UNION SELECT 3 as dev_Order, "Game Console"
UNION SELECT 3 as dev_Order, "SmartTV"
UNION SELECT 3 as dev_Order, "TV Decoder"
UNION SELECT 3 as dev_Order, "Virtual Assistance"
UNION SELECT 4 as dev_Order, "Clock"
UNION SELECT 4 as dev_Order, "House Appliance"
UNION SELECT 4 as dev_Order, "Phone"
UNION SELECT 4 as dev_Order, "Radio"
-- network devices
UNION SELECT 5 as dev_Order, "AP"
UNION SELECT 5 as dev_Order, "Gateway"
UNION SELECT 5 as dev_Order, "Firewall"
UNION SELECT 5 as dev_Order, "Hypervisor"
UNION SELECT 5 as dev_Order, "Powerline"
UNION SELECT 5 as dev_Order, "Switch"
UNION SELECT 5 as dev_Order, "WLAN"
UNION SELECT 5 as dev_Order, "PLC"
UNION SELECT 5 as dev_Order, "Router"
UNION SELECT 5 as dev_Order, "USB LAN Adapter"
UNION SELECT 5 as dev_Order, "USB WIFI Adapter"
UNION SELECT 10 as dev_Order, "Other"
ORDER BY 1,2';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_DeviceType']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of groups
//------------------------------------------------------------------------------
function getGroups() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 1 as dev_Order, dev_Group
FROM Devices
WHERE dev_Group NOT IN ("(unknown)", "Others") AND dev_Group <> ""
UNION SELECT 1 as dev_Order, "Always on"
UNION SELECT 1 as dev_Order, "Friends"
UNION SELECT 1 as dev_Order, "Personal"
UNION SELECT 2 as dev_Order, "Others"
ORDER BY 1,2 ';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Group']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of locations
//------------------------------------------------------------------------------
function getLocations() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 9 as dev_Order, dev_Location
FROM Devices
WHERE dev_Location <> ""
AND dev_Location NOT IN (
"Bathroom", "Bedroom", "Dining room", "Hallway",
"Kitchen", "Laundry", "Living room", "Study",
"Attic", "Basement", "Garage",
"Back yard", "Garden", "Terrace",
"Other")
UNION SELECT 1 as dev_Order, "Bathroom"
UNION SELECT 1 as dev_Order, "Bedroom"
UNION SELECT 1 as dev_Order, "Dining room"
UNION SELECT 1 as dev_Order, "Hall"
UNION SELECT 1 as dev_Order, "Kitchen"
UNION SELECT 1 as dev_Order, "Laundry"
UNION SELECT 1 as dev_Order, "Living room"
UNION SELECT 1 as dev_Order, "Study"
UNION SELECT 2 as dev_Order, "Attic"
UNION SELECT 2 as dev_Order, "Basement"
UNION SELECT 2 as dev_Order, "Garage"
UNION SELECT 3 as dev_Order, "Back yard"
UNION SELECT 3 as dev_Order, "Garden"
UNION SELECT 3 as dev_Order, "Terrace"
UNION SELECT 10 as dev_Order, "Other"
ORDER BY 1,2 ';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Location']);
}
// Return json
echo (json_encode ($tableData));
}
// ----------------------------------------------------------------------------------------
function updateNetworkLeaf()
{

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// events.php - Front module. Server side. Manage Events

View File

@@ -1,7 +1,7 @@
<?php
###################################################################################
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# internetinfo.php # Front module. Server side. System Information #

View File

@@ -1,7 +1,7 @@
<?php
###################################################################################
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# nslookup.php # Front module. Server side. System Information #

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// parameters.php - Front module. Server side. Manage Parameters

View File

@@ -1,7 +1,7 @@
<?php
###################################################################################
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# traceroute.php # Front module. Server side. System Information #

View File

@@ -1,6 +1,6 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// NetAlertX
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// util.php - Front module. Server side. Common generic functions
@@ -185,7 +185,7 @@ function displayMessage($message, $logAlert = FALSE, $logConsole = TRUE, $logFil
echo '<script>alert(escape("'.$message.'"));</script>';
}
// F12 Browser console
// F12 Browser dev console
if($logConsole)
{
echo '<script>console.log(escape("'.str_replace('"',"'",$message).'"));</script>';
@@ -194,16 +194,26 @@ function displayMessage($message, $logAlert = FALSE, $logConsole = TRUE, $logFil
//File
if($logFile)
{
if(file_exists($logFolderPath.$log_file) != 1) // file doesn't exist, create one
{
$log = fopen($logFolderPath.$log_file, "w") or die("Unable to open file!");
}else // file exists, append
{
$log = fopen($logFolderPath.$log_file, "a") or die("Unable to open file!");
if (is_writable($logFolderPath.$log_file)) {
if(file_exists($logFolderPath.$log_file) != 1) // file doesn't exist, create one
{
$log = fopen($logFolderPath.$log_file, "w") or die("Unable to open file!");
}else // file exists, append
{
$log = fopen($logFolderPath.$log_file, "a") or die("Unable to open file - Permissions issue!");
}
fwrite($log, "[".$timestamp. "] " . str_replace('<br>',"\n ",str_replace('<br/>',"\n ",$message)).PHP_EOL."" );
fclose($log);
} else {
echo 'The file is not writable: '.$logFolderPath.$log_file;
}
fwrite($log, "[".$timestamp. "] " . str_replace('<br>',"\n ",str_replace('<br/>',"\n ",$message)).PHP_EOL."" );
fclose($log);
}
//echo
@@ -240,7 +250,7 @@ function cleanLog($logFile)
$path = "";
$allowedFiles = ['pialert.log', 'pialert_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', "pialert_pholus_lastrun.log", 'pialert.php_errors.log'];
$allowedFiles = ['app.log', 'app_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', "pholus_lastrun.log", 'app.php_errors.log'];
if(in_array($logFile, $allowedFiles))
{
@@ -282,7 +292,7 @@ function saveSettings()
}
// generate a clean pialert.conf file
// generate a clean .conf file
$groups = [];
$txt = "";
@@ -292,7 +302,7 @@ function saveSettings()
$txt = $txt."# Generated: ".$timestamp." #\n";
$txt = $txt."# #\n";
$txt = $txt."# Config file for the LAN intruder detection app: #\n";
$txt = $txt."# https://github.com/jokob-sk/Pi.Alert #\n";
$txt = $txt."# https://github.com/jokob-sk/NetAlertX #\n";
$txt = $txt."# #\n";
$txt = $txt."#-----------------AUTOGENERATED FILE-----------------#\n";
@@ -377,7 +387,7 @@ function saveSettings()
// Replace the original file with the temporary file
rename($tempConfPath, $fullConfPath);
displayMessage("<br/>Settings saved to the <code>pialert.conf</code> file.<br/><br/>A time-stamped backup of the previous file created. <br/><br/> Reloading...<br/>",
displayMessage("<br/>Settings saved to the <code>app.conf</code> file.<br/><br/>A time-stamped backup of the previous file created. <br/><br/> Reloading...<br/>",
FALSE, TRUE, TRUE, TRUE);
}

View File

@@ -1,6 +1,6 @@
<?php
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# build.php - Templates module Template to display the current build version #
@@ -11,7 +11,7 @@
# cvc90 2023 https://github.com/cvc90 GNU GPLv3 #
#---------------------------------------------------------------------------------#
$file = "/home/pi/pialert/front/buildtimestamp.txt";
$file = "/app/front/buildtimestamp.txt";
if (file_exists($file)) {
echo date("Y-m-d", ((int)file_get_contents($file)));
}

View File

@@ -1,6 +1,6 @@
<!--
#---------------------------------------------------------------------------------#
# Pi.Alert #
# NetAlertX #
# Open Source Network Guard / WIFI & LAN intrusion detector #
# #
# footer.php - Front module. Common footer to all the web pages #
@@ -16,19 +16,20 @@
<footer class="main-footer">
<!-- Default to the left -->
<!-- &copy; 2022 jokob-sk -->
<span style="display:inline-block; transform: rotate(180deg)">&copy;</span>
2020 Puche (2022+ <a href="mailto:jokob@duck.com?subject=PiAlert">jokob-sk</a>) | <b><?= lang('Maintenance_built_on');?>: </b>
<?php include 'php/templates/build.php'; ?> | <b> Version: </b> <?php include 'php/templates/version.php'; ?> |
<a href="https://github.com/jokob-sk/Pi.Alert/tree/main/docs" target="_blank"><span>Docs <i class="fa fa-circle-question"></i></a>
<span>
<!-- NetAlertX footer with url -->
<a href="https://github.com/jokob-sk/NetAlertX" target="_blank">Net <b>Alert</b><sup>x</sup></a>
<!-- To the right -->
<div class="pull-right no-hidden-xs">
<!-- Pi.Alert footer with url -->
<a href="https://github.com/jokob-sk/Pi.Alert" target="_blank">Pi.Alert</a>
| <a href="https://github.com/jokob-sk/NetAlertX/tree/main/docs" target="_blank">Docs <i class="fa fa-circle-question"></i></a>
| <a href="https://github.com/jokob-sk/NetAlertX/issues"><i class="fa-solid fa-bug"></i></a>
| <a href="https://github.com/jokob-sk/NetAlertX/"><i class="fa-brands fa-github"></i></a>
| <a href="mailto:jokob@duck.com?subject=NetAlertX"><i class="fa-solid fa-envelope"></i></a>
| <a href="https://github.com/pucherot/Pi.Alert">&copy;</a>
| <?= lang('Maintenance_built_on');?>: <?php include 'php/templates/build.php'; ?>
| Version: <?php include 'php/templates/version.php'; ?>
|
</div>
</footer>
@@ -54,9 +55,13 @@
<!-- FastClick -->
<!-- <script src="lib/AdminLTE/bower_components/fastclick/lib/fastclick.js"></script> -->
<!-- Pi.Alert -------------------------------------------------------------- -->
<script src="js/pialert_common.js"></script>
<!-- NetAlertX -------------------------------------------------------------- -->
<script src="js/handle_version.js"></script>
<?php
require 'migrationCheck.php';
?>
</body>
</html>

View File

@@ -1,5 +1,5 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# NetAlertX
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# header.php - Front module. Common header to all the web pages
@@ -21,17 +21,17 @@ require dirname(__FILE__).'/security.php';
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="manifest" href="img/manifest.json">
<title>Pi.Alert - <?php echo gethostname();?></title>
<title>Net Alert ✖ - <?php echo gethostname();?></title>
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- ----------------------------------------------------------------------- -->
<!-- REQUIRED JS SCRIPTS -->
<!-- jQuery 3 -->
<script src="lib/AdminLTE/bower_components/jquery/dist/jquery.min.js"></script>
<script src="js/common.js"></script>
<!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/bootstrap/dist/css/bootstrap.min.css">
@@ -53,8 +53,8 @@ require dirname(__FILE__).'/security.php';
apply the skin class to the body tag so the changes take effect. -->
<link rel="stylesheet" href="lib/AdminLTE/dist/css/skins/<?php echo $pia_skin_selected;?>.min.css">
<!-- Pi.Alert CSS -->
<link rel="stylesheet" href="css/pialert.css">
<!-- NetAlertX CSS -->
<link rel="stylesheet" href="css/app.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@@ -66,7 +66,7 @@ require dirname(__FILE__).'/security.php';
<!-- Google Font -->
<!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> -->
<link rel="stylesheet" href="css/offline-font.css">
<link rel="icon" type="image/x-icon" href="img/pialertLogoOrange.png">
<link rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
<!-- For better UX on Mobile Devices using the Shortcut on the Homescreen -->
<link rel="manifest" href="img/manifest.json">
@@ -111,20 +111,29 @@ if ($ENABLED_DARKMODE === True) {
<!-- ----------------------------------------------------------------------- -->
<!-- Layout Boxed Yellow -->
<body class="hold-transition <?php echo $pia_skin_selected;?> sidebar-mini" <?php echo $BACKGROUND_IMAGE_PATCH;?> onLoad="show_pia_servertime();" >
<body class="hold-transition fixed <?php echo $pia_skin_selected;?> sidebar-mini" <?php echo $BACKGROUND_IMAGE_PATCH;?> onLoad="show_pia_servertime();" >
<!-- Site wrapper -->
<div class="wrapper">
<!-- Main Header -->
<header class="main-header">
<!-- ----------------------------------------------------------------------- -->
<!-- Logo -->
<a href="devices.php" class="logo">
<!-- mini logo for sidebar mini 50x50 pixels -->
<span class="logo-mini">P<b>a</b></span>
<span class="logo-mini">
<img src="img/NetAlertX_logo.png" class="pia-top-left-logo" alt="NetAlertX Logo"/>
</span>
<!-- logo for regular state and mobile devices -->
<span class="logo-lg">Pi<b>.Alert</b></span>
<span class="logo-lg">Net <b>Alert</b><sup>x</sup>
</span>
</a>
<!-- ----------------------------------------------------------------------- -->
@@ -134,25 +143,29 @@ if ($ENABLED_DARKMODE === True) {
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<i class="fa-solid fa-bars"></i>
</a>
<!-- ticker message Placeholder for ticker announcement messages -->
<div id="ticker_announcement_plc"></div>
<!-- Navbar Right Menu -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!-- Back Button -->
<li>
<a id="back-button" href="javascript:history.go(-1);" role="button" span class='of-bt-icon'><i class='fa fa-arrow-left'></i></a>
</li>
<!-- Next Button -->
<li>
<a id="next-button" href="javascript:history.go(1);" role="button" span class='of-bt-icon'><i class='fa fa-arrow-right'></i></a>
</li>
<!-- Reload -->
<li>
<a id="reload-button" href='#' role="button" span class='of-bt-icon' onclick='location.reload()'><i class='fa fa-repeat'></i></a>
</li>
<!-- Full Screen -->
<li>
<a id="fullscreen-button" href='#' role="button" span class='of-bt-icon' onclick='toggleFullscreen()'><i class='fa fa-arrows-alt'></i></a>
</li>
<ul class="nav navbar-nav">
<!-- Back Button -->
<li>
<a id="back-button" href="javascript:history.go(-1);" role="button" span class='of-bt-icon'><i class='fa fa-arrow-left'></i></a>
</li>
<!-- Next Button -->
<li>
<a id="next-button" href="javascript:history.go(1);" role="button" span class='of-bt-icon'><i class='fa fa-arrow-right'></i></a>
</li>
<!-- Clear cache & Reload -->
<li>
<a id="reload-button" href='#' role="button" span class='of-bt-icon' onclick='clearCache()'><i class='fa fa-repeat'></i></a>
</li>
<!-- Full Screen -->
<li>
<a id="fullscreen-button" href='#' role="button" span class='of-bt-icon' onclick='toggleFullscreen()'><i class='fa fa-arrows-alt'></i></a>
</li>
<!-- Server Status -->
<li>
<a onclick="setCache('activeMaintenanceTab', 'tab_Logging_id')" href="maintenance.php#tab_Logging">
@@ -173,17 +186,17 @@ if ($ENABLED_DARKMODE === True) {
<!-- Menu Toggle Button -->
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<!-- The user image in the navbar-->
<img src="img/pialertLogoWhite.png" class="user-image" style="border-radius: initial" alt="Pi.Alert Logo">
<img src="img/NetAlertX_logo.png" class="user-image" style="border-radius: initial" alt="NetAlertX Logo">
<!-- hidden-xs hides the username on small devices so only the image appears. -->
<span class="hidden-xs">Pi.Alert</span>
<span class="hidden-xs">Net <b>Alert</b><sup>x</sup></span>
</a>
<ul class="dropdown-menu">
<!-- The user image in the menu -->
<li class="user-header" style=" height: 100px;">
<img src="img/pialertLogoWhite.png" class="img-circle" alt="Pi.Alert Logo" style="border-color:transparent; height: 50px; width: 50px; margin-top:15px;">
<img src="img/NetAlertX_logo.png" class="img-circle NetAlertX-logo" alt="NetAlertX Logo">
<p style="float: right; width: 200px">
<?= lang('About_Title');?>
<small><?= lang('About_Design');?> Raspberry Pi</small>
<small><?= lang('About_Design');?> Docker</small>
</p>
</li>
@@ -199,8 +212,12 @@ if ($ENABLED_DARKMODE === True) {
</ul>
</div>
</nav>
</header>
<!-- ----------------------------------------------------------------------- -->
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
@@ -208,62 +225,175 @@ if ($ENABLED_DARKMODE === True) {
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- Sidebar user panel (optional) -->
<div class="user-panel"> <a href="." class="logo">
<img src="img/pialertLogoGray80.png" class="img-responsive" alt="Pi.Alert Logo"/>
</a>
</div>
<!-- search form (Optional) -->
<!-- DELETED -->
<!-- Sidebar Menu -->
<!-- Navigation Mneu -->
<ul class="sidebar-menu" data-widget="tree">
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'active'; } ?>">
<a href="devices.php"><i class="fa fa-laptop"></i> <span><?= lang('Navigation_Devices');?></span></a>
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'active menu-open'; } ?>">
<a href="#" onclick="openUrl(['./devices.php', './deviceDetails.php'])">
<i class="fa fa-fw fa-laptop"></i> <span><?= lang('Navigation_Devices');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<a href="devices.php#my" onclick="initializeDatatable('my')" > <?= lang("Device_Shortcut_AllDevices");?> </a>
</li>
<li>
<a href="devices.php#connected" onclick="initializeDatatable('connected')" > <?= lang("Device_Shortcut_Connected");?> </a>
</li>
<li>
<a href="devices.php#favorites" onclick="initializeDatatable('favorites')" > <?= lang("Device_Shortcut_Favorites");?> </a>
</li>
<li>
<a href="devices.php#new" onclick="initializeDatatable('new')" > <?= lang("Device_Shortcut_NewDevices");?> </a>
</li>
<li>
<a href="devices.php#down" onclick="initializeDatatable('down')" > <?= lang("Device_Shortcut_DownAlerts");?> </a>
</li>
<li>
<a href="devices.php#down_only" onclick="initializeDatatable('down_only')" > <?= lang("Device_Shortcut_DownOnly");?> </a>
</li>
<li>
<a href="devices.php#archived" onclick="initializeDatatable('archived')" > <?= lang("Device_Shortcut_Archived");?> </a>
</li>
</ul>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('presence.php') ) ){ echo 'active'; } ?>">
<a href="presence.php"><i class="fa fa-calendar"></i> <span><?= lang('Navigation_Presence');?></span></a>
<!-- Monitoring menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('presence.php', 'report.php', 'events.php' ) ) ){ echo 'active menu-open'; } ?>">
<a href="#">
<i class="fa fa-fw fa-chart-bar"></i> <span><?= lang('Navigation_Monitoring');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('presence.php', 'report.php', 'events.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<a href="presence.php"> <?= lang("Navigation_Presence");?> </a>
</li>
<li>
<a href="events.php"> <?= lang("Navigation_Events");?> </a>
</li>
<li>
<a href="report.php"> <?= lang("Navigation_Report");?> </a>
</li>
</ul>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('events.php') ) ){ echo 'active'; } ?>">
<a href="events.php"><i class="fa fa-bolt"></i> <span><?= lang('Navigation_Events');?></span></a>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('report.php') ) ){ echo 'active'; } ?>">
<a href="report.php"><i class="fa fa-flag"></i> <span><?= lang('Navigation_Report');?></span></a>
</li>
<!-- Network menu item -->
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('network.php') ) ){ echo 'active'; } ?>">
<a href="network.php"><i class="fa fa-fw fa-network-wired"></i> <span><?= lang('Navigation_Network');?></span></a>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php') ) ){ echo 'active'; } ?>">
<a href="plugins.php"><i class="fa fa-fw fa-plug"></i> <span><?= lang('Navigation_Plugins');?></span></a>
<!-- Maintenance menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('maintenance.php') ) ){ echo 'active menu-open'; } ?>">
<a href="#" onclick="openUrl(['./maintenance.php'])">
<div class="info-icon-nav myhidden" id="version" data-build-time="<?php echo file_get_contents( "buildtimestamp.txt");?>">🆕</div>
<i class="fa fa-fw fa-wrench"></i> <span><?= lang('Navigation_Maintenance');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('maintenance.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<a href="maintenance.php#tab_Settings" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_UISettings");?> </a>
</li>
<li>
<a href="maintenance.php#tab_DBTools" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_Tools");?> </a>
</li>
<li>
<a href="maintenance.php#tab_BackupRestore" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_BackupRestore");?> </a>
</li>
<li>
<a href="maintenance.php#tab_Logging" onclick="initializeTabs()"> <?= lang("Maintenance_Tools_Tab_Logging");?> </a>
</li>
<li>
<a href="maintenance.php#tab_multiEdit" onclick="initializeTabs()"> <?= lang("Device_MultiEdit");?> </a>
</li>
</ul>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('maintenance.php') ) ){ echo 'active'; } ?>">
<div class="info-icon-nav myhidden" id="version" data-build-time="<?php echo file_get_contents( "buildtimestamp.txt");?>">🆕</div>
<a href="maintenance.php"><i class="fa fa-wrench "></i> <span><?= lang('Navigation_Maintenance');?></span></a>
<!-- Settings menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('settings.php') ) ){ echo 'active menu-open'; } ?>">
<a href="#" onclick="openUrl(['./settings.php'])">
<i class="fa fa-fw fa-cog"></i> <span><?= lang('Navigation_Settings');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu" style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('settings.php') ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<a href="settings.php#pageTitle"> <?= lang("settings_enabled");?> </a>
</li>
<li>
<a href="settings.php#core_content_header"> <?= lang("settings_core_label");?> </a>
</li>
<li>
<a href="settings.php#system_content_header"> <?= lang("settings_system_label");?> </a>
</li>
<li>
<a href="settings.php#device_scanner_content_header"> <?= lang("settings_device_scanners_label");?> </a>
</li>
<li>
<a href="settings.php#other_content_header"> <?= lang("settings_other_scanners_label");?> </a>
</li>
<li>
<a href="settings.php#publisher_content_header"> <?= lang("settings_publishers_label");?> </a>
</li>
</ul>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('settings.php') ) ){ echo 'active'; } ?>">
<a href="settings.php"><i class="fa fa-cog"></i> <span><?= lang('Navigation_Settings');?></span></a>
<!-- Integrations menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php' ) ) ){ echo 'active menu-open'; } ?>">
<a href="#">
<i class="fa fa-fw fa-plug"></i> <span><?= lang('Navigation_Integrations');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<div class="info-icon-nav work-in-progress"> </div>
<a href="workflows.php"><?= lang('Navigation_Workflows');?></a>
</li>
<li>
<a href="plugins.php"><?= lang("Navigation_Plugins");?> </a>
</li>
</ul>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('workflows.php') ) ){ echo 'active'; } ?>">
<div class="info-icon-nav work-in-progress"> </div>
<a href="workflows.php"><i class="fa fa-shuffle"></i> <span><?= lang('Navigation_Workflows');?></span></a>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active'; } ?>">
<a href="systeminfo.php"><i class="fa fa-microchip"></i> <span><?= lang('Navigation_SystemInfo');?></span></a>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('help_faq.php') ) ){ echo 'active'; } ?>">
<a href="help_faq.php"><i class="fa fa-question"></i> <span><?= lang('Navigation_HelpFAQ');?></span></a>
</li>
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('donations.php') ) ){ echo 'active'; } ?>">
<a href="donations.php"><i class="fa fa-heart"></i> <span><?= lang('Navigation_Donations');?></span></a>
<!-- About menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('donations.php', 'help_faq.php', 'systeminfo.php' ) ) ){ echo 'active menu-open'; } ?>">
<a href="#">
<i class="fa fa-fw fa-info"></i> <span><?= lang('Navigation_About');?></span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('donations.php', 'help_faq.php', 'systeminfo.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
<li>
<a href="donations.php"> <?= lang("Navigation_Donations");?> </a>
</li>
<li>
<a href="help_faq.php"> <?= lang("Navigation_HelpFAQ");?> </a>
</li>
<li>
<a href="systeminfo.php"> <?= lang("Navigation_SystemInfo");?> </a>
</li>
</ul>
</li>
</ul>
<!-- /.sidebar-menu -->
@@ -271,11 +401,25 @@ if ($ENABLED_DARKMODE === True) {
<!-- /.sidebar -->
</aside>
<script src="js/pialert_common.js"></script>
<script defer>
// Generate work-in-progress icons
function workInProgress() {
if($(".work-in-progress").html().trim() == "")
{
$(".work-in-progress").append(`
<a href="https://github.com/jokob-sk/NetAlertX/issues" target="_blank">
<b class="pointer" title="${getString("Gen_Work_In_Progress")}">🦺</b>
</a>
`)
}
}
//--------------------------------------------------------------
//--------------------------------------------------------------
function toggleFullscreen() {
@@ -295,5 +439,6 @@ if ($ENABLED_DARKMODE === True) {
// Update server state in the header
updateState()
workInProgress()
</script>

View File

@@ -1,5 +1,5 @@
{
"API_CUSTOM_SQL_description": "Benutzerdefinierte SQL-Abfrage, welche eine JSON-Datei generiert und diese mit dem <a href=\"/api/table_custom_endpoint.json\" target=\"_blank\">Dateiendpunkt <code>table_custom_endpoint.json</code></a> zur Verfügung stellt.",
"API_CUSTOM_SQL_description": "Benutzerdefinierte SQL-Abfrage, welche eine JSON-Datei generiert und diese mit dem <a href=\"/api/table_custom_endpoint.json\" target=\"_blank\">Dateiendpunkt <code>table_custom_endpoint.json</code></a> zur Verf\u00fcgung stellt.",
"API_CUSTOM_SQL_name": "Benutzerdefinierte SQL-Abfrage",
"API_display_name": "API",
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
@@ -20,11 +20,11 @@
"AppEvents_Helper1": "Helfer 1",
"AppEvents_Helper2": "Helfer 2",
"AppEvents_Helper3": "Helfer 3",
"AppEvents_ObjectForeignKey": "Unbekannter Schlüssel",
"AppEvents_ObjectForeignKey": "Unbekannter Schl\u00fcssel",
"AppEvents_ObjectIndex": "Index",
"AppEvents_ObjectIsArchived": "Ist archiviert (Zum Protokoll Zeitpunkt)",
"AppEvents_ObjectIsNew": "Ist neu (Zum Protokoll Zeitpunkt)",
"AppEvents_ObjectPlugin": "Verknüpfte Plugins",
"AppEvents_ObjectPlugin": "Verkn\u00fcpfte Plugins",
"AppEvents_ObjectPrimaryID": "",
"AppEvents_ObjectSecondaryID": "",
"AppEvents_ObjectStatus": "",
@@ -39,49 +39,49 @@
"BackDevDetail_Actions_Title_Run": "Run action",
"BackDevDetail_Copy_Ask": "Copy details from device from the dropdown list (Everything on this page will be overwritten)?",
"BackDevDetail_Copy_Title": "Copy details",
"BackDevDetail_Tools_WOL_error": "Befehl wurde NICHT ausgeführt.",
"BackDevDetail_Tools_WOL_okay": "Befehl wurde ausgeführt.",
"BackDevDetail_Tools_WOL_error": "Befehl wurde NICHT ausgef\u00fchrt.",
"BackDevDetail_Tools_WOL_okay": "Befehl wurde ausgef\u00fchrt.",
"BackDevices_Arpscan_disabled": "Automatischer Arp-Scan deaktiviert.",
"BackDevices_Arpscan_enabled": "Automatischer Arp-Scan aktiviert.",
"BackDevices_Backup_CopError": "Die originale Datenbank konnte nicht gesichert werden.",
"BackDevices_Backup_Failed": "Das Backup wurde teilweise ausgeführt. Das Archiv ist entweder leer oder nicht vorhanden.",
"BackDevices_Backup_Failed": "Das Backup wurde teilweise ausgef\u00fchrt. Das Archiv ist entweder leer oder nicht vorhanden.",
"BackDevices_Backup_okay": "Das Backup wurde erfolgreich beendet.",
"BackDevices_DBTools_DelActHistory": "Die Anzeige der Netzwerkaktivität wurde zurückgesetzt.",
"BackDevices_DBTools_DelActHistoryError": "Fehler beim Zurücksetzen der Netzwerkaktivitätsanzeige.",
"BackDevices_DBTools_DelDevError_a": "Fehler beim Löschen des Gerätes.",
"BackDevices_DBTools_DelDevError_b": "Fehler beim Löschen der Geräte.",
"BackDevices_DBTools_DelDev_a": "Gerät erfolgreich gelöscht.",
"BackDevices_DBTools_DelDev_b": "Geräte erfolgreich gelöscht.",
"BackDevices_DBTools_DelEvents": "Events erfolgreich gelöscht.",
"BackDevices_DBTools_DelEventsError": "Fehler beim Löschen der Ereignisse.",
"BackDevices_DBTools_ImportCSV": "Die Geräte aus der CSV-Datei wurden erfolgreich importiert.",
"BackDevices_DBTools_DelActHistory": "Die Anzeige der Netzwerkaktivit\u00e4t wurde zur\u00fcckgesetzt.",
"BackDevices_DBTools_DelActHistoryError": "Fehler beim Zur\u00fccksetzen der Netzwerkaktivit\u00e4tsanzeige.",
"BackDevices_DBTools_DelDevError_a": "Fehler beim L\u00f6schen des Ger\u00e4tes.",
"BackDevices_DBTools_DelDevError_b": "Fehler beim L\u00f6schen der Ger\u00e4te.",
"BackDevices_DBTools_DelDev_a": "Ger\u00e4t erfolgreich gel\u00f6scht.",
"BackDevices_DBTools_DelDev_b": "Ger\u00e4te erfolgreich gel\u00f6scht.",
"BackDevices_DBTools_DelEvents": "Events erfolgreich gel\u00f6scht.",
"BackDevices_DBTools_DelEventsError": "Fehler beim L\u00f6schen der Ereignisse.",
"BackDevices_DBTools_ImportCSV": "Die Ger\u00e4te aus der CSV-Datei wurden erfolgreich importiert.",
"BackDevices_DBTools_ImportCSVError": "Die CSV-Datei konnte nicht importiert werden. Stellen Sie sicher, dass das Format korrekt ist.",
"BackDevices_DBTools_ImportCSVMissing": "Die CSV-Datei konnte nicht in <b>/config/devices.csv</b> gefunden werden.",
"BackDevices_DBTools_Purge": "Die ältesten Backups wurden gelöscht.",
"BackDevices_DBTools_UpdDev": "Gerät erfolgreich aktualisiert.",
"BackDevices_DBTools_UpdDevError": "Fehler beim Aktualisieren des Gerätes.",
"BackDevices_DBTools_Purge": "Die \u00e4ltesten Backups wurden gel\u00f6scht.",
"BackDevices_DBTools_UpdDev": "Ger\u00e4t erfolgreich aktualisiert.",
"BackDevices_DBTools_UpdDevError": "Fehler beim Aktualisieren des Ger\u00e4tes.",
"BackDevices_DBTools_Upgrade": "Datenbank erfolgreich aktualisiert.",
"BackDevices_DBTools_UpgradeError": "Fehler beim Aktualisieren der Datenbank.",
"BackDevices_Device_UpdDevError": "Konnte Geräte nicht aktualisieren, versuchen Sie es später erneut. Die Datenbank ist wahrscheinlich wegen einer laufenden Aufgabe gesperrt.",
"BackDevices_Device_UpdDevError": "Konnte Ger\u00e4te nicht aktualisieren, versuchen Sie es sp\u00e4ter erneut. Die Datenbank ist wahrscheinlich wegen einer laufenden Aufgabe gesperrt.",
"BackDevices_Restore_CopError": "Die originale Datenbank konnte nicht kopiert werden.",
"BackDevices_Restore_Failed": "Die Wiederherstellung ist fehlgeschlagen. Stellen Sie das Backup manuell her.",
"BackDevices_Restore_okay": "Die Wiederherstellung wurde erfolgreich ausgeführt.",
"BackDevices_Restore_okay": "Die Wiederherstellung wurde erfolgreich ausgef\u00fchrt.",
"BackDevices_darkmode_disabled": "Heller Modus aktiviert.",
"BackDevices_darkmode_enabled": "Dunkler Modus aktiviert.",
"DAYS_TO_KEEP_EVENTS_description": "Dies ist eine Wartungseinstellung. Spezifiziert wie viele Tage Events gespeichert bleiben. Alle älteren Events werden periodisch gelöscht. Wird auch auf die Plugins History angewendet.",
"DAYS_TO_KEEP_EVENTS_name": "Lösche Events älter als",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Details von Gerät kopieren",
"DAYS_TO_KEEP_EVENTS_description": "Dies ist eine Wartungseinstellung. Spezifiziert wie viele Tage Events gespeichert bleiben. Alle \u00e4lteren Events werden periodisch gel\u00f6scht. Wird auch auf die Plugins History angewendet.",
"DAYS_TO_KEEP_EVENTS_name": "L\u00f6sche Events \u00e4lter als",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Details von Ger\u00e4t kopieren",
"DevDetail_Copy_Device_Tooltip": "Copy details from device from the dropdown list. Everything on this page will be overwritten",
"DevDetail_EveandAl_AlertAllEvents": "Melde alle Ereignisse",
"DevDetail_EveandAl_AlertDown": "Melde Down",
"DevDetail_EveandAl_Archived": "Archivierung",
"DevDetail_EveandAl_NewDevice": "Neues Gerät",
"DevDetail_EveandAl_NewDevice": "Neues Ger\u00e4t",
"DevDetail_EveandAl_NewDevice_Tooltip": "",
"DevDetail_EveandAl_RandomMAC": "Zufällige MAC",
"DevDetail_EveandAl_RandomMAC": "Zuf\u00e4llige MAC",
"DevDetail_EveandAl_ScanCycle": "Scan Abstand",
"DevDetail_EveandAl_ScanCycle_a": "Gerät scannen",
"DevDetail_EveandAl_ScanCycle_z": "Gerät nicht scannen",
"DevDetail_EveandAl_Skip": "pausiere wiederhol. Meldungen für",
"DevDetail_EveandAl_ScanCycle_a": "Ger\u00e4t scannen",
"DevDetail_EveandAl_ScanCycle_z": "Ger\u00e4t nicht scannen",
"DevDetail_EveandAl_Skip": "pausiere wiederhol. Meldungen f\u00fcr",
"DevDetail_EveandAl_Title": "Ereignisse & Alarme einstellen",
"DevDetail_Events_CheckBox": "Blende Verbindungs-Ereignisse aus",
"DevDetail_GoToNetworkNode": "Navigate to the Network page of the given node.",
@@ -96,7 +96,7 @@
"DevDetail_MainInfo_Network": "Netzwerk Knoten",
"DevDetail_MainInfo_Network_Port": "Netzwerk Knoten Port",
"DevDetail_MainInfo_Network_Title": "<i class=\"fa fa-network-wired\"></i> Network",
"DevDetail_MainInfo_Owner": "Eigen&shy;tümer",
"DevDetail_MainInfo_Owner": "Eigen&shy;t\u00fcmer",
"DevDetail_MainInfo_Title": "Haupt Infos",
"DevDetail_MainInfo_Type": "Typ",
"DevDetail_MainInfo_Vendor": "Hersteller",
@@ -104,31 +104,31 @@
"DevDetail_Network_Node_hover": "Select the parent network device the current device is connected to to populate the Network tree.",
"DevDetail_Network_Port_hover": "The port this device is connected to on the parent network device. If left empty a wifi icon is displayed in the Network tree.",
"DevDetail_Nmap_Scans": "Nmap Scans",
"DevDetail_Nmap_Scans_desc": "Hier kannst du manuelle NMAP Scans starten. Reguläre automatische NMAP Scans können mit dem Services & Ports (NMAP) Plugin geplant werden. Gehe zu den <a href='/settings.php' target='_blank'>Einstellungen</a> um mehr herauszufinden.",
"DevDetail_Nmap_Scans_desc": "Hier kannst du manuelle NMAP Scans starten. Regul\u00e4re automatische NMAP Scans k\u00f6nnen mit dem Services & Ports (NMAP) Plugin geplant werden. Gehe zu den <a href='/settings.php' target='_blank'>Einstellungen</a> um mehr herauszufinden.",
"DevDetail_Nmap_buttonDefault": "Standard Scan",
"DevDetail_Nmap_buttonDefault_text": "Standard Scan: Nmap scannt die ersten 1.000 Ports für jedes angeforderte Scan-Protokoll. Damit werden etwa 93 % der TCP-Ports und 49 % der UDP-Ports erfasst. (ca. 5-10 Sekunden)",
"DevDetail_Nmap_buttonDefault_text": "Standard Scan: Nmap scannt die ersten 1.000 Ports f\u00fcr jedes angeforderte Scan-Protokoll. Damit werden etwa 93 % der TCP-Ports und 49 % der UDP-Ports erfasst. (ca. 5-10 Sekunden)",
"DevDetail_Nmap_buttonDetail": "Detailierter Scan",
"DevDetail_Nmap_buttonDetail_text": "Detailierter Scan: Standardscan mit aktivierter Betriebssystemerkennung, Versionserkennung, Skript-Scan und Traceroute (bis zu 30 oder mehr Sekunden)",
"DevDetail_Nmap_buttonFast": "Schneller Scan",
"DevDetail_Nmap_buttonFast_text": "Schneller Scan: Überprüft nur die wichtigsten 100 Ports (wenige Sekunden)",
"DevDetail_Nmap_buttonSkipDiscovery": "Ohne Erreichbarkeitsprüfung",
"DevDetail_Nmap_buttonSkipDiscovery_text": "Ohne Erreichbarkeitsprüfung (-Pn Parameter): Standard Scan bei dem nmap annimmt, dass der Host erreichbar ist.",
"DevDetail_Nmap_resultsLink": "Nachdem ein Scan gestartet wurde, kann diese Seite verlassen werden. Resultate sind auch in der Datei <code>pialert_front.log</code> verfügbar.",
"DevDetail_Owner_hover": "Der Eigentümer des Gerätes. Freies Textfeld.",
"DevDetail_Nmap_buttonFast_text": "Schneller Scan: \u00dcberpr\u00fcft nur die wichtigsten 100 Ports (wenige Sekunden)",
"DevDetail_Nmap_buttonSkipDiscovery": "Ohne Erreichbarkeitspr\u00fcfung",
"DevDetail_Nmap_buttonSkipDiscovery_text": "Ohne Erreichbarkeitspr\u00fcfung (-Pn Parameter): Standard Scan bei dem nmap annimmt, dass der Host erreichbar ist.",
"DevDetail_Nmap_resultsLink": "Nachdem ein Scan gestartet wurde, kann diese Seite verlassen werden. Resultate sind auch in der Datei <code>app_front.log</code> verf\u00fcgbar.",
"DevDetail_Owner_hover": "Der Eigent\u00fcmer des Ger\u00e4tes. Freies Textfeld.",
"DevDetail_Periodselect_All": "Alle Infos",
"DevDetail_Periodselect_LastMonth": "Letzter Monat",
"DevDetail_Periodselect_LastWeek": "Letzte Woche",
"DevDetail_Periodselect_LastYear": "Letztes Jahr",
"DevDetail_Periodselect_today": "Heute",
"DevDetail_Run_Actions_Title": "<i class=\"fa fa-play\"></i> Aktion auf Gerät ausführen",
"DevDetail_Run_Actions_Tooltip": "Eine Aktion aus der Dropdown-Liste auf dem aktuellen Gerät ausführen.",
"DevDetail_Run_Actions_Title": "<i class=\"fa fa-play\"></i> Aktion auf Ger\u00e4t ausf\u00fchren",
"DevDetail_Run_Actions_Tooltip": "Eine Aktion aus der Dropdown-Liste auf dem aktuellen Ger\u00e4t ausf\u00fchren.",
"DevDetail_SessionInfo_FirstSession": "Erste Sitzung",
"DevDetail_SessionInfo_LastIP": "Letzte IP",
"DevDetail_SessionInfo_LastSession": "Letzte Sitzung",
"DevDetail_SessionInfo_StaticIP": "Statische IP",
"DevDetail_SessionInfo_Status": "Status",
"DevDetail_SessionInfo_Title": "Sitzungsinfos",
"DevDetail_SessionTable_Additionalinfo": "Zusätzliche Info",
"DevDetail_SessionTable_Additionalinfo": "Zus\u00e4tzliche Info",
"DevDetail_SessionTable_Connection": "Verbindung",
"DevDetail_SessionTable_Disconnection": "Trennung",
"DevDetail_SessionTable_Duration": "Dauer",
@@ -143,60 +143,69 @@
"DevDetail_Tab_EventsTableDate": "Datum",
"DevDetail_Tab_EventsTableEvent": "Ereignistype",
"DevDetail_Tab_EventsTableIP": "IP",
"DevDetail_Tab_EventsTableInfo": "Zusätzliche Informationen",
"DevDetail_Tab_EventsTableInfo": "Zus\u00e4tzliche Informationen",
"DevDetail_Tab_Nmap": "Nmap",
"DevDetail_Tab_NmapEmpty": "An diesem Gerät wurden keine offenen Ports mit Nmap gefunden.",
"DevDetail_Tab_NmapEmpty": "An diesem Ger\u00e4t wurden keine offenen Ports mit Nmap gefunden.",
"DevDetail_Tab_NmapTableExtra": "Extra",
"DevDetail_Tab_NmapTableHeader": "Ergebnisse geplanter Scans",
"DevDetail_Tab_NmapTableIndex": "Index",
"DevDetail_Tab_NmapTablePort": "Port",
"DevDetail_Tab_NmapTableService": "Dienst",
"DevDetail_Tab_NmapTableState": "Status",
"DevDetail_Tab_NmapTableText": "Erstelle einen Plan über die<a href=\"/settings.php#NMAP_ACTIVE\">Einstellungen</a>",
"DevDetail_Tab_NmapTableText": "Erstelle einen Plan \u00fcber die<a href=\"/settings.php#NMAP_ACTIVE\">Einstellungen</a>",
"DevDetail_Tab_NmapTableTime": "Zeit",
"DevDetail_Tab_Plugins": "<i class=\"fa fa-plug\"></i> Plugins",
"DevDetail_Tab_Presence": "Anwesenheit",
"DevDetail_Tab_Sessions": "Sitzungen",
"DevDetail_Tab_Tools": "<i class=\"fa fa-screwdriver-wrench\"></i> Tools",
"DevDetail_Tab_Tools_Internet_Info_Description": "Das Internet-Info-Tool zeigt Informationen über die Internetverbindung an, wie z. B. IP-Adresse, Stadt, Land, Ortsvorwahl und Zeitzone.",
"DevDetail_Tab_Tools_Internet_Info_Description": "Das Internet-Info-Tool zeigt Informationen \u00fcber die Internetverbindung an, wie z. B. IP-Adresse, Stadt, Land, Ortsvorwahl und Zeitzone.",
"DevDetail_Tab_Tools_Internet_Info_Error": "Es ist ein Fehler aufgetreten",
"DevDetail_Tab_Tools_Internet_Info_Start": "Internet-Info starten",
"DevDetail_Tab_Tools_Internet_Info_Title": "Internetinformationen",
"DevDetail_Tab_Tools_Nslookup_Description": "Nslookup ist ein Befehlszeilentool zur Abfrage des Domain Name System (DNS). DNS ist ein System, das Domainnamen wie www.google.com in IP-Adressen wie 172.217.0.142 übersetzt. ",
"DevDetail_Tab_Tools_Nslookup_Error": "Fehler: IP-Adresse ist ungültig",
"DevDetail_Tab_Tools_Nslookup_Description": "Nslookup ist ein Befehlszeilentool zur Abfrage des Domain Name System (DNS). DNS ist ein System, das Domainnamen wie www.google.com in IP-Adressen wie 172.217.0.142 \u00fcbersetzt. ",
"DevDetail_Tab_Tools_Nslookup_Error": "Fehler: IP-Adresse ist ung\u00fcltig",
"DevDetail_Tab_Tools_Nslookup_Start": "Nslookup starten",
"DevDetail_Tab_Tools_Nslookup_Title": "Nslookup",
"DevDetail_Tab_Tools_Speedtest_Description": "Das Speedtest-Tool misst die Download-Geschwindigkeit, Upload-Geschwindigkeit und Latenz der Internetverbindung.",
"DevDetail_Tab_Tools_Speedtest_Start": "Speedtest starten",
"DevDetail_Tab_Tools_Speedtest_Title": "Speedtest test",
"DevDetail_Tab_Tools_Traceroute_Description": "Traceroute ist ein Netzwerkdiagnosebefehl, mit dem der Pfad verfolgt wird, den Datenpakete von einem Host zu einem anderen nehmen.<br><br>Der Befehl verwendet das Internet Control Message Protocol (ICMP), um Pakete an Zwischenknoten auf der Route zu senden, jeden Zwischenknoten Der Knoten antwortet mit einem ICMP-Timeout-Paket (TTL-Zeitüberschreitung).<br><br>Die Ausgabe des Traceroute-Befehls zeigt die IP-Adresse jedes Zwischenknotens auf der Route an.<br><br>Die Ausgabe der Traceroute Der Befehl zeigt die IP-Adresse jedes Zwischenknotens auf der Route an.<br><br>Der Befehl traceroute kann zur Diagnose von Netzwerkproblemen wie Verzögerungen, Paketverlust und blockierten Routen verwendet werden.<br><br>Das ist auch möglich kann verwendet werden, um den Standort eines Zwischenknotens in einem Netzwerk zu identifizieren.",
"DevDetail_Tab_Tools_Traceroute_Error": "Fehler: IP-Adresse ist ungültig",
"DevDetail_Tab_Tools_Traceroute_Description": "Traceroute ist ein Netzwerkdiagnosebefehl, mit dem der Pfad verfolgt wird, den Datenpakete von einem Host zu einem anderen nehmen.<br><br>Der Befehl verwendet das Internet Control Message Protocol (ICMP), um Pakete an Zwischenknoten auf der Route zu senden, jeden Zwischenknoten Der Knoten antwortet mit einem ICMP-Timeout-Paket (TTL-Zeit\u00fcberschreitung).<br><br>Die Ausgabe des Traceroute-Befehls zeigt die IP-Adresse jedes Zwischenknotens auf der Route an.<br><br>Die Ausgabe der Traceroute Der Befehl zeigt die IP-Adresse jedes Zwischenknotens auf der Route an.<br><br>Der Befehl \u201etraceroute\u201c kann zur Diagnose von Netzwerkproblemen wie Verz\u00f6gerungen, Paketverlust und blockierten Routen verwendet werden.<br><br>Das ist auch m\u00f6glich kann verwendet werden, um den Standort eines Zwischenknotens in einem Netzwerk zu identifizieren.",
"DevDetail_Tab_Tools_Traceroute_Error": "Fehler: IP-Adresse ist ung\u00fcltig",
"DevDetail_Tab_Tools_Traceroute_Start": "Traceroute starten",
"DevDetail_Tab_Tools_Traceroute_Title": "Traceroute",
"DevDetail_Tools_WOL": "Sende Wol Befehl an ",
"DevDetail_Tools_WOL_noti": "Wake-on-LAN",
"DevDetail_Tools_WOL_noti_text": "Der Wake-on-LAN Befehl wurd and die Broadcast Adresse gesendet. Wenn sich das zu startende Gerät nicht im gleichen Subnet/vlan wie Pi.Alert befindet, wird das Gerät nicht reagieren.",
"DevDetail_Type_hover": "Der Type des Gerätes. If you select any of the pre-defined network devices (e.g.: AP, Firewall, Router, Switch...) they will show up in the Network tree configuration as possible parent network nodes.",
"DevDetail_Tools_WOL_noti_text": "Der Wake-on-LAN Befehl wurd and die Broadcast Adresse gesendet. Wenn sich das zu startende Ger\u00e4t nicht im gleichen Subnet/vlan wie Pi.Alert befindet, wird das Ger\u00e4t nicht reagieren.",
"DevDetail_Type_hover": "Der Type des Ger\u00e4tes. If you select any of the pre-defined network devices (e.g.: AP, Firewall, Router, Switch...) they will show up in the Network tree configuration as possible parent network nodes.",
"DevDetail_Vendor_hover": "Vendor should be auto-detected. You can overwrite or add your custom value.",
"DevDetail_WOL_Title": "<i class=\"fa fa-power-off\"></i> Wake-on-LAN",
"DevDetail_button_Delete": "Lösche Gerät",
"DevDetail_button_DeleteEvents": "Lösche Events",
"DevDetail_button_DeleteEvents_Warning": "Sind Sie sicher, dass Sie alle Ereignisse dieses Geräts löschen möchten? (dies löscht den Ereignisverlauf und die Sitzungen und könnte bei ständigen (anhaltenden) Benachrichtigungen helfen)",
"DevDetail_button_AddIcon": "",
"DevDetail_button_AddIcon_Help": "",
"DevDetail_button_AddIcon_Tooltip": "",
"DevDetail_button_Delete": "L\u00f6sche Ger\u00e4t",
"DevDetail_button_DeleteEvents": "L\u00f6sche Events",
"DevDetail_button_DeleteEvents_Warning": "Sind Sie sicher, dass Sie alle Ereignisse dieses Ger\u00e4ts l\u00f6schen m\u00f6chten? (dies l\u00f6scht den Ereignisverlauf und die Sitzungen und k\u00f6nnte bei st\u00e4ndigen (anhaltenden) Benachrichtigungen helfen)",
"DevDetail_button_OverwriteIcons": "Overwrite Icons",
"DevDetail_button_OverwriteIcons_Tooltip": "Overwrite icons of all devices with the same device type",
"DevDetail_button_OverwriteIcons_Warning": "Are you sure you want to overwrite all icons of all devices with the same device type as the current device type?",
"DevDetail_button_Reset": "Verwerfen",
"DevDetail_button_Save": "Speichern",
"Device_MultiEdit": "",
"Device_MultiEdit_Backup": "",
"Device_MultiEdit_Fields": "",
"Device_MultiEdit_MassActions": "",
"Device_MultiEdit_Tooltip": "",
"Device_Searchbox": "Suche",
"Device_Shortcut_AllDevices": "Alle Geräte",
"Device_Shortcut_AllDevices": "Alle Ger\u00e4te",
"Device_Shortcut_Archived": "Archiviert",
"Device_Shortcut_Connected": "Verbunden",
"Device_Shortcut_Devices": "Geräte",
"Device_Shortcut_Devices": "Ger\u00e4te",
"Device_Shortcut_DownAlerts": "Down Meldungen",
"Device_Shortcut_DownOnly": "",
"Device_Shortcut_Favorites": "Favoriten",
"Device_Shortcut_NewDevices": "Neue Geräte",
"Device_Shortcut_OnlineChart": "Gerätepräsenz im Laufe der Zeit",
"Device_TableHead_Connected_Devices": "Verbundene Geräte",
"Device_Shortcut_NewDevices": "Neue Ger\u00e4te",
"Device_Shortcut_OnlineChart": "Ger\u00e4tepr\u00e4senz im Laufe der Zeit",
"Device_TableHead_Connected_Devices": "Verbundene Ger\u00e4te",
"Device_TableHead_Favorite": "Favorit",
"Device_TableHead_FirstSession": "Erste Sitzung",
"Device_TableHead_Group": "Gruppe",
@@ -208,26 +217,26 @@
"Device_TableHead_MAC": "MAC",
"Device_TableHead_MAC_full": "Gesamte MAC",
"Device_TableHead_Name": "Name",
"Device_TableHead_Owner": "Eigentümer",
"Device_TableHead_Parent_MAC": "Übergeordnete MAC",
"Device_TableHead_Owner": "Eigent\u00fcmer",
"Device_TableHead_Parent_MAC": "\u00dcbergeordnete MAC",
"Device_TableHead_Port": "Port",
"Device_TableHead_RowID": "",
"Device_TableHead_Rowid": "Zeilennummer",
"Device_TableHead_Status": "Status",
"Device_TableHead_Type": "Typ",
"Device_TableHead_Vendor": "Hersteller",
"Device_Table_Not_Network_Device": "Nicht konfiguriert als Netzwerkgerät",
"Device_Table_info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"Device_Table_nav_next": "Nächste",
"Device_Table_nav_prev": "Zurück",
"Device_Tablelenght": "Zeige _MENU_ Einträge",
"Device_Table_Not_Network_Device": "Nicht konfiguriert als Netzwerkger\u00e4t",
"Device_Table_info": "Zeige _START_ bis _END_ von _TOTAL_ Eintr\u00e4gen",
"Device_Table_nav_next": "N\u00e4chste",
"Device_Table_nav_prev": "Zur\u00fcck",
"Device_Tablelenght": "Zeige _MENU_ Eintr\u00e4ge",
"Device_Tablelenght_all": "Alle",
"Device_Title": "Geräte",
"Device_Title": "Ger\u00e4te",
"Donations_Others": "Others",
"Donations_Platforms": "Sponsor platforms",
"Donations_Text": "Hey 👋! </br> Thanks for clicking on this menu item 😅 </br> </br> I'm trying to collect some donations to make you better software. Also, it would help me not to get burned out. Me burning out might mean end of support for this app. Any small (recurring or not) sponsorship makes me want ot put more effort into this app. I don't want to lock features (new plugins) behind paywalls 🔐. </br> Currently, I'm waking up 2h before work so I contribute to the app a bit. If I had some recurring income I could shorten my workweek and in the remaining time fully focus on PiAlert. You'd get more functionality, a more polished app and less bugs. </br> </br> Thanks for reading - I'm super grateful for any support ❤🙏 </br> </br> TL;DR: By supporting me you get: </br> </br> <ul><li>Regular updates to keep your data and family safe 🔄</li><li>Less bugs 🐛🔫</li><li>Better and more functionality</li><li>I don't get burned out 🔥🤯</li><li>Less rushed releases 💨</li><li>Better docs📚</li><li>Quicker and better support with issues 🆘</li><li>Less grumpy me 😄</li></ul> </br> 📧Email me to <a href='mailto:jokob@duck.com?subject=PiAlert'>jokob@duck.com</a> if you want to get in touch or if I should add other sponsorship platforms. </br>",
"Donations_Text": "Hey \ud83d\udc4b! </br> Thanks for clicking on this menu item \ud83d\ude05 </br> </br> I'm trying to collect some donations to make you better software. Also, it would help me not to get burned out. Me burning out might mean end of support for this app. Any small (recurring or not) sponsorship makes me want ot put more effort into this app. I don't want to lock features (new plugins) behind paywalls \ud83d\udd10. </br> Currently, I'm waking up 2h before work so I contribute to the app a bit. If I had some recurring income I could shorten my workweek and in the remaining time fully focus on NetAlertX. You'd get more functionality, a more polished app and less bugs. </br> </br> Thanks for reading - I'm super grateful for any support \u2764\ud83d\ude4f </br> </br> TL;DR: By supporting me you get: </br> </br> <ul><li>Regular updates to keep your data and family safe \ud83d\udd04</li><li>Less bugs \ud83d\udc1b\ud83d\udd2b</li><li>Better and more functionality\u2795</li><li>I don't get burned out \ud83d\udd25\ud83e\udd2f</li><li>Less rushed releases \ud83d\udca8</li><li>Better docs\ud83d\udcda</li><li>Quicker and better support with issues \ud83c\udd98</li><li>Less grumpy me \ud83d\ude04</li></ul> </br> \ud83d\udce7Email me to <a href='mailto:jokob@duck.com?subject=NetAlertX'>jokob@duck.com</a> if you want to get in touch or if I should add other sponsorship platforms. </br>",
"Donations_Title": "Donations",
"ENABLE_PLUGINS_description": "NOTUSED Enables the <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins\">plugins</a> functionality. Loading plugins requires more hardware resources so you might want to disable them on low-powered system.",
"ENABLE_PLUGINS_description": "NOTUSED Enables the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins\">plugins</a> functionality. Loading plugins requires more hardware resources so you might want to disable them on low-powered system.",
"ENABLE_PLUGINS_name": "NOTUSED Enable Plugins",
"Email_display_name": "Email",
"Email_icon": "<i class=\"fa fa-at\"></i>",
@@ -242,13 +251,13 @@
"Events_Shortcut_DownAlerts": "Down Meldungen",
"Events_Shortcut_Events": "Ereignisse",
"Events_Shortcut_MissSessions": "fehlende Sitzungen",
"Events_Shortcut_NewDevices": "Neue Geräte",
"Events_Shortcut_NewDevices": "Neue Ger\u00e4te",
"Events_Shortcut_Sessions": "Sitzungen",
"Events_Shortcut_VoidSessions": "beendete Sitzungen",
"Events_TableHead_AdditionalInfo": "Zusätzliche Info",
"Events_TableHead_AdditionalInfo": "Zus\u00e4tzliche Info",
"Events_TableHead_Connection": "Verbindung",
"Events_TableHead_Date": "Datum",
"Events_TableHead_Device": "Gerät",
"Events_TableHead_Device": "Ger\u00e4t",
"Events_TableHead_Disconnection": "Trennung",
"Events_TableHead_Duration": "Dauer",
"Events_TableHead_DurationOrder": "Duration Order",
@@ -256,11 +265,11 @@
"Events_TableHead_IP": "IP",
"Events_TableHead_IPOrder": "IP Order",
"Events_TableHead_Order": "Order",
"Events_TableHead_Owner": "Eigentümer",
"Events_Table_info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"Events_Table_nav_next": "Nächste",
"Events_Table_nav_prev": "Zurück",
"Events_Tablelenght": "Zeige _MENU_ Einträge",
"Events_TableHead_Owner": "Eigent\u00fcmer",
"Events_Table_info": "Zeige _START_ bis _END_ von _TOTAL_ Eintr\u00e4gen",
"Events_Table_nav_next": "N\u00e4chste",
"Events_Table_nav_prev": "Zur\u00fcck",
"Events_Tablelenght": "Zeige _MENU_ Eintr\u00e4ge",
"Events_Tablelenght_all": "Alle",
"Events_Title": "Ereignisse",
"Gen_Action": "Action",
@@ -269,17 +278,18 @@
"Gen_Cancel": "Abbrechen",
"Gen_Copy": "Run",
"Gen_DataUpdatedUITakesTime": "OK - It may take a while for the UI to update if a scan is runnig",
"Gen_Delete": "Löschen",
"Gen_Delete": "L\u00f6schen",
"Gen_DeleteAll": "Delete all",
"Gen_Error": "",
"Gen_LockedDB": "ERROR - DB eventuell gesperrt - Nutze die Konsole in den Entwickler Werkzeugen (F12) zur Überprüfung oder probiere es später erneut.",
"Gen_LockedDB": "ERROR - DB eventuell gesperrt - Nutze die Konsole in den Entwickler Werkzeugen (F12) zur \u00dcberpr\u00fcfung oder probiere es sp\u00e4ter erneut.",
"Gen_Okay": "Ok",
"Gen_Purge": "Aufräumen",
"Gen_Purge": "Aufr\u00e4umen",
"Gen_ReadDocs": "Mehr in der Dokumentation",
"Gen_Restore": "Wiederherstellen",
"Gen_Run": "Run",
"Gen_Save": "Speichern",
"Gen_Saved": "Gespeichert",
"Gen_Selected_Devices": "",
"Gen_Switch": "Umschalten",
"Gen_Upd": "Aktualisierung erfolgreich",
"Gen_Upd_Fail": "Aktualisierung fehlgeschlagen",
@@ -287,56 +297,56 @@
"Gen_Work_In_Progress": "",
"General_display_name": "Allgemein",
"General_icon": "<i class=\"fa fa-gears\"></i>",
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung. Geräte markiert als <b>Neues Gerät</b> werden gelöscht, wenn ihre <b>Erste Sitzung</b> länger her ist als die angegebenen Stunden in dieser Einstellung. <code>0</code> deaktiviert diese Funktion. Nutzen Sie diese Einstellung, um <b>Neue Geräte</b> automatisch nach <code>X</code> Stunden zu löschen.",
"HRS_TO_KEEP_NEWDEV_name": "Neue Geräte speichern für",
"HRS_TO_KEEP_NEWDEV_description": "Dies ist eine Wartungseinstellung. Ger\u00e4te markiert als <b>Neues Ger\u00e4t</b> werden gel\u00f6scht, wenn ihre <b>Erste Sitzung</b> l\u00e4nger her ist als die angegebenen Stunden in dieser Einstellung. <code>0</code> deaktiviert diese Funktion. Nutzen Sie diese Einstellung, um <b>Neue Ger\u00e4te</b> automatisch nach <code>X</code> Stunden zu l\u00f6schen.",
"HRS_TO_KEEP_NEWDEV_name": "Neue Ger\u00e4te speichern f\u00fcr",
"HelpFAQ_Cat_Detail": "Detailansicht",
"HelpFAQ_Cat_Detail_300_head": "Was bedeutet ",
"HelpFAQ_Cat_Detail_300_text_a": "meint ein Netzwerkgerät (welches den typ AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router,USB LAN Adapter, USB WIFI Adapter, or Internet eingestellt hat)",
"HelpFAQ_Cat_Detail_300_text_b": "bezeichnet die Anschlussnummer/Portnummer, an der das gerade bearbeitete Gerät mit diesem Netzwerkgerät verbunden ist.",
"HelpFAQ_Cat_Detail_300_text_a": "meint ein Netzwerkger\u00e4t (welches den typ AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router,USB LAN Adapter, USB WIFI Adapter, or Internet eingestellt hat)",
"HelpFAQ_Cat_Detail_300_text_b": "bezeichnet die Anschlussnummer/Portnummer, an der das gerade bearbeitete Ger\u00e4t mit diesem Netzwerkger\u00e4t verbunden ist.",
"HelpFAQ_Cat_Detail_301_head_a": "Wann wird nun gescannt? Bei ",
"HelpFAQ_Cat_Detail_301_head_b": " steht 1min aber der Graph zeigt 5min - Abstände an.",
"HelpFAQ_Cat_Detail_301_text": "Den zeitlichen Abstand zwischen den Scans legt der \"Cronjob\" fest, welcher standardmäßig auf 5min eingestellt ist. Die Benennung \"1min\" bezieht sich auf die zu erwartende Dauer des Scans. Abhängig vor der Netzwerkkonfiguration kann diese Zeitangabe variieren. Um den Cronjob zu bearbeiten, kannst du im Terminal/der Konsole <span class=\"text-danger help_faq_code\">crontab -e</span> eingeben und den Intervall ändern.",
"HelpFAQ_Cat_Detail_301_head_b": " steht 1min aber der Graph zeigt 5min - Abst\u00e4nde an.",
"HelpFAQ_Cat_Detail_301_text": "Den zeitlichen Abstand zwischen den Scans legt der \"Cronjob\" fest, welcher standardm\u00e4\u00dfig auf 5min eingestellt ist. Die Benennung \"1min\" bezieht sich auf die zu erwartende Dauer des Scans. Abh\u00e4ngig vor der Netzwerkkonfiguration kann diese Zeitangabe variieren. Um den Cronjob zu bearbeiten, kannst du im Terminal/der Konsole <span class=\"text-danger help_faq_code\">crontab -e</span> eingeben und den Intervall \u00e4ndern.",
"HelpFAQ_Cat_Detail_302_head_a": "Was bedeutet ",
"HelpFAQ_Cat_Detail_302_head_b": " und warum kann ich das nicht auswählen?",
"HelpFAQ_Cat_Detail_302_text": "Einige moderne Geräte generieren aus Datenschutzgründen zufällige MAC-Adressen, die keinem Hersteller mehr zugeordnet werden können und welche sich mit jeder neuen Verbindung ändern. Pi.Alert erkennt, ob es sich um eine solche zufällige MAC-Adresse handelt und aktiviert dieses \"Feld\" automatisch. Um das Verhalten abzustellen, musst du in deinem Endgerät schauen, wie du die MAC-Adressen-Generierung deaktivierst.",
"HelpFAQ_Cat_Detail_302_head_b": " und warum kann ich das nicht ausw\u00e4hlen?",
"HelpFAQ_Cat_Detail_302_text": "Einige moderne Ger\u00e4te generieren aus Datenschutzgr\u00fcnden zuf\u00e4llige MAC-Adressen, die keinem Hersteller mehr zugeordnet werden k\u00f6nnen und welche sich mit jeder neuen Verbindung \u00e4ndern. Pi.Alert erkennt, ob es sich um eine solche zuf\u00e4llige MAC-Adresse handelt und aktiviert dieses \"Feld\" automatisch. Um das Verhalten abzustellen, musst du in deinem Endger\u00e4t schauen, wie du die MAC-Adressen-Generierung deaktivierst.",
"HelpFAQ_Cat_Detail_303_head": "Was ist Nmap und wozu dient es?",
"HelpFAQ_Cat_Detail_303_text": "Nmap ist ein Netzwerkscanner mit vielfältigen Möglichkeiten.<br> Wenn ein neues Gerät in deiner Liste auftaucht, hast du die Möglichkeit über den Nmap-Scan genauere Informationen über das Gerät zu erhalten.",
"HelpFAQ_Cat_Device_200_head": "Ich habe, mir nicht bekannte, Geräte in meiner Liste. Nach dem Löschen tauchen diese immer wieder auf.",
"HelpFAQ_Cat_Device_200_text": "Wenn du Pi-hole verwendest, beachte bitte, dass Pi.Alert Informationen von Pi-hole abruft. Pausiere Pi.Alert, gehe in Pi-hole auf die Settings-Seite und lösche ggf. die betreffende DHCP-Lease. Anschließend schaue, ebenfalls in Pi-hole, unter Tools -> Network, ob sich dort die immer wiederkehrenden Hosts finden lassen. Wenn ja, lösche diese dort ebenfalls. Nun kannst du Pi.Alert wieder starten. Jetzt sollte das Gerät/die Geräte nicht mehr auftauchen.",
"HelpFAQ_Cat_Detail_303_text": "Nmap ist ein Netzwerkscanner mit vielf\u00e4ltigen M\u00f6glichkeiten.<br> Wenn ein neues Ger\u00e4t in deiner Liste auftaucht, hast du die M\u00f6glichkeit \u00fcber den Nmap-Scan genauere Informationen \u00fcber das Ger\u00e4t zu erhalten.",
"HelpFAQ_Cat_Device_200_head": "Ich habe, mir nicht bekannte, Ger\u00e4te in meiner Liste. Nach dem L\u00f6schen tauchen diese immer wieder auf.",
"HelpFAQ_Cat_Device_200_text": "Wenn du Pi-hole verwendest, beachte bitte, dass Pi.Alert Informationen von Pi-hole abruft. Pausiere Pi.Alert, gehe in Pi-hole auf die Settings-Seite und l\u00f6sche ggf. die betreffende DHCP-Lease. Anschlie\u00dfend schaue, ebenfalls in Pi-hole, unter Tools -> Network, ob sich dort die immer wiederkehrenden Hosts finden lassen. Wenn ja, l\u00f6sche diese dort ebenfalls. Nun kannst du Pi.Alert wieder starten. Jetzt sollte das Ger\u00e4t/die Ger\u00e4te nicht mehr auftauchen.",
"HelpFAQ_Cat_General": "Allgemein",
"HelpFAQ_Cat_General_100_head": "Die Uhr oben rechts und die Zeiten der Events/Anwesenheit stimmen nicht überein (Zeitverschiebung).",
"HelpFAQ_Cat_General_100_text_a": "Auf deinem PC ist für die PHP Umgebung folgende Zeitzone voreingestellt:",
"HelpFAQ_Cat_General_100_text_b": "Sollte dies nicht die Zeitzone sein, in der du dich aufhältst, solltest du die Zeitzone in der PHP Konfigurationsdatei anpassen. Diese findest du in diesem Verzeichnis:",
"HelpFAQ_Cat_General_100_text_c": "Suche in dieser Datei nach dem Eintrag 'date.timezone', entferne ggf. das führende ';' und trage die gewünschte Zeitzone ein. Eine Liste mit den unterstützten Zeitzonen findest du hier (<a href=\"https://www.php.net/manual/de/timezones.php\" target=\"blank\">Link</a>).",
"HelpFAQ_Cat_General_100_head": "Die Uhr oben rechts und die Zeiten der Events/Anwesenheit stimmen nicht \u00fcberein (Zeitverschiebung).",
"HelpFAQ_Cat_General_100_text_a": "Auf deinem PC ist f\u00fcr die PHP Umgebung folgende Zeitzone voreingestellt:",
"HelpFAQ_Cat_General_100_text_b": "Sollte dies nicht die Zeitzone sein, in der du dich aufh\u00e4ltst, solltest du die Zeitzone in der PHP Konfigurationsdatei anpassen. Diese findest du in diesem Verzeichnis:",
"HelpFAQ_Cat_General_100_text_c": "Suche in dieser Datei nach dem Eintrag 'date.timezone', entferne ggf. das f\u00fchrende ';' und trage die gew\u00fcnschte Zeitzone ein. Eine Liste mit den unterst\u00fctzten Zeitzonen findest du hier (<a href=\"https://www.php.net/manual/de/timezones.php\" target=\"blank\">Link</a>).",
"HelpFAQ_Cat_General_101_head": "Mein Netzwerk scheint langsamer zu werden, Streaming ruckelt.",
"HelpFAQ_Cat_General_101_text": "Es kann durchaus sein, das leistungsschwache Geräte mit der Art und Weise, wie Pi.Alert neue Geräte im Netzwerk erkennt, an ihre Leistungsgrenzen kommen. Dies verstärkt sich noch einmal, <br/> wenn diese Geräte per WLAN mit dem Netzwerk kommunizieren. Lösungen wären hier, wenn möglich ein Wechsel auf eine Kabelverbindung oder, falls das Geräte nur einen begrenzten Zeitraum genutzt <br/> werden soll, den arp-Scan auf der Wartungsseite zu pausieren.",
"HelpFAQ_Cat_General_102_head": "Ich bekomme die Meldung, dass die Datenbank schreibgeschützt (read only) ist.",
"HelpFAQ_Cat_General_102_text": "Prüfe im Pi.Alert verzeichnis ob der Ordner der Datenbank (db) die richtigen Rechte zugewiesen bekommen hat:<br> <span class=\"text-danger help_faq_code\">drwxrwx--- 2 (dein Username) www-data</span><br> Sollte die Berechtigung nicht stimmen, kannst du sie mit folgenden Befehlen im Terminal oder der Konsole wieder setzen:<br> <span class=\"text-danger help_faq_code\"> sudo chgrp -R www-data ~/pialert/db<br> chmod -R 770 ~/pialert/db </span><br> Wenn die Datenbank danach noch immer schreibgeschützt ist, versuche eine erneute Installation, oder das Zuückspielen eines Datenbank-Backups über die Wartungsseite.",
"HelpFAQ_Cat_General_102docker_head": "(🐳 Docker only) Database issues (AJAX errors, read-only, not found)",
"HelpFAQ_Cat_General_102docker_text": "Double-check you have followed the <a href=\"https://github.com/jokob-sk/Pi.Alert/tree/main/dockerfiles\">dockerfile readme (most up-to-date info)</a>. <br/> <br/> <ul data-sourcepos=\"49:4-52:146\" dir=\"auto\"> <li data-sourcepos=\"49:4-49:106\">Download the <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/db/pialert.db\">original DB from GitHub</a>.</li> <li data-sourcepos=\"50:4-50:195\">Map the <code>pialert.db</code> file (<g-emoji class=\"g-emoji\" alias=\"warning\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/26a0.png\"></g-emoji> not folder) from above to <code>/home/pi/pialert/db/pialert.db</code> (see <a href=\"https://github.com/jokob-sk/Pi.Alert/tree/main/dockerfiles#-examples\">Examples</a> for details).</li><li data-sourcepos=\"51:4-51:161\">If facing issues (AJAX errors, can not write to DB, etc,) make sure permissions are set correctly, alternatively check the logs under <code>/home/pi/pialert/front/log</code>.</li> <li data-sourcepos=\"52:4-52:146\">To solve permission issues you can also try to create a DB backup and then run a DB Restore via the <strong>Maintenance &gt; Backup/Restore</strong> section.</li> <li data-sourcepos=\"53:4-53:228\">If the database is in read-only mode you can solve this by setting the owner and group by executing the following command on the host system: <code>docker exec pialert chown -R www-data:www-data /home/pi/pialert/db/pialert.db</code>.</li></ul>",
"HelpFAQ_Cat_General_103_head": "Die Login-Seite erscheint nicht, auch nicht nach der Passwortänderung.",
"HelpFAQ_Cat_General_103_text": "Neben dem Passwort, muss in der Konfigurationsdatei <span class=\"text-danger help_faq_code\">~/pialert/config/pialert.conf</span> auch der Parameter <span class=\"text-danger help_faq_code\">PIALERT_WEB_PROTECTION</span> auf <span class=\"text-danger help_faq_code\">True</span> gesetzt sein.",
"HelpFAQ_Cat_General_101_text": "Es kann durchaus sein, das leistungsschwache Ger\u00e4te mit der Art und Weise, wie NetAlertX neue Ger\u00e4te im Netzwerk erkennt, an ihre Leistungsgrenzen kommen. Dies verst\u00e4rkt sich noch einmal, <br/> wenn diese Ger\u00e4te per WLAN mit dem Netzwerk kommunizieren. L\u00f6sungen w\u00e4ren hier, wenn m\u00f6glich ein Wechsel auf eine Kabelverbindung oder, falls das Ger\u00e4te nur einen begrenzten Zeitraum genutzt <br/> werden soll, den arp-Scan auf der Wartungsseite zu pausieren.",
"HelpFAQ_Cat_General_102_head": "Ich bekomme die Meldung, dass die Datenbank schreibgesch\u00fctzt (read only) ist.",
"HelpFAQ_Cat_General_102_text": "Pr\u00fcfe im NetAlertX verzeichnis ob der Ordner der Datenbank (db) die richtigen Rechte zugewiesen bekommen hat:<br> <span class=\"text-danger help_faq_code\">drwxrwx--- 2 (dein Username) www-data</span><br> Sollte die Berechtigung nicht stimmen, kannst du sie mit folgenden Befehlen im Terminal oder der Konsole wieder setzen:<br> <span class=\"text-danger help_faq_code\"> sudo chgrp -R www-data /app/db<br> chmod -R 770 /app/db </span><br> Wenn die Datenbank danach noch immer schreibgesch\u00fctzt ist, versuche eine erneute Installation, oder das Zu\u00fcckspielen eines Datenbank-Backups \u00fcber die Wartungsseite.",
"HelpFAQ_Cat_General_102docker_head": "(\ud83d\udc33 Docker only) Database issues (AJAX errors, read-only, not found)",
"HelpFAQ_Cat_General_102docker_text": "Double-check you have followed the <a href=\"https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles\">dockerfile readme (most up-to-date info)</a>. <br/> <br/> <ul data-sourcepos=\"49:4-52:146\" dir=\"auto\"> <li data-sourcepos=\"49:4-49:106\">Download the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/db/app.db\">original DB from GitHub</a>.</li> <li data-sourcepos=\"50:4-50:195\">Map the <code>app.db</code> file (<g-emoji class=\"g-emoji\" alias=\"warning\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/26a0.png\">\u26a0</g-emoji> not folder) from above to <code>/app/db/app.db</code> (see <a href=\"https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles#-examples\">Examples</a> for details).</li><li data-sourcepos=\"51:4-51:161\">If facing issues (AJAX errors, can not write to DB, etc,) make sure permissions are set correctly, alternatively check the logs under <code>/app/front/log</code>.</li> <li data-sourcepos=\"52:4-52:146\">To solve permission issues you can also try to create a DB backup and then run a DB Restore via the <strong>Maintenance &gt; Backup/Restore</strong> section.</li> <li data-sourcepos=\"53:4-53:228\">If the database is in read-only mode you can solve this by setting the owner and group by executing the following command on the host system: <code>docker exec netalertx chown -R www-data:www-data /app/db/app.db</code>.</li></ul>",
"HelpFAQ_Cat_General_103_head": "Die Login-Seite erscheint nicht, auch nicht nach der Passwort\u00e4nderung.",
"HelpFAQ_Cat_General_103_text": "Neben dem Passwort, muss in der Konfigurationsdatei <span class=\"text-danger help_faq_code\">/app/config/app.conf</span> auch der Parameter <span class=\"text-danger help_faq_code\">PIALERT_WEB_PROTECTION</span> auf <span class=\"text-danger help_faq_code\">True</span> gesetzt sein.",
"HelpFAQ_Cat_Network_600_head": "Was bringt mir diese Seite?",
"HelpFAQ_Cat_Network_600_text": "Diese Seite soll dir die Möglichkeit bieten, die Belegung deiner Netzwerkgeräte abzubilden. Dazu kannst du einen oder mehrere Switches, WLANs, Router, etc. erstellen, sie ggf. mit einer Portanzahl versehen und bereits erkannte Geräte diesen zuordnen. Diese Zuordnung erfolgt in der Detailansicht, des zuzuordnenden Gerätes. So ist es dir möglich, schnell festzustellen an welchem Port ein Host angeschlossen und ob er online ist.",
"HelpFAQ_Cat_Network_600_text": "Diese Seite soll dir die M\u00f6glichkeit bieten, die Belegung deiner Netzwerkger\u00e4te abzubilden. Dazu kannst du einen oder mehrere Switches, WLANs, Router, etc. erstellen, sie ggf. mit einer Portanzahl versehen und bereits erkannte Ger\u00e4te diesen zuordnen. Diese Zuordnung erfolgt in der Detailansicht, des zuzuordnenden Ger\u00e4tes. So ist es dir m\u00f6glich, schnell festzustellen an welchem Port ein Host angeschlossen und ob er online ist.",
"HelpFAQ_Cat_Network_601_head": "Gibt es mehr Dokumentation?",
"HelpFAQ_Cat_Network_601_text": "Ja, gibt es! Siehe <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/\">alle Dokumentationen</a> für mehr Infos.",
"HelpFAQ_Cat_Presence_400_head": "Geräte werden mit einer gelben Markierung und dem Hinweis \"missing Event\" angezeigt.",
"HelpFAQ_Cat_Presence_400_text": "Wenn dies geschieht hast du die Möglickeit, bei dem betreffenden Gerät (Detailsansicht) die Events zu löschen. Eine andere Möglichkeit wäre, das Gerät einzuschalten und zu warten, bis Pi.Alert mit dem nächsten Scan das Gerät als \"Online\" erkennt und anschließend das Gerät einfach wieder ausschalten. Nun sollte Pi.Alert mit dem nächsten Scan den Zustand des Gerätes ordentlich in der Datenbank vermerken.",
"HelpFAQ_Cat_Presence_401_head": "Ein Gerät wird als Anwesend angezeigt, obwohl es \"Offline\" ist.",
"HelpFAQ_Cat_Presence_401_text": "Wenn dies geschieht hast du die Möglickeit, bei dem betreffenden Gerät (Detailsansicht) die Events zu löschen. Eine andere Möglichkeit wäre, das Gerät einzuschalten und zu warten, bis Pi.Alert mit dem nächsten Scan das Gerät als \"Online\" erkennt und anschließend das Gerät einfach wieder ausschalten. Nun sollte Pi.Alert mit dem nächsten Scan den Zustand des Gerätes ordentlich in der Datenbank vermerken.",
"HelpFAQ_Cat_Network_601_text": "Ja, gibt es! Siehe <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/\">alle Dokumentationen</a> f\u00fcr mehr Infos.",
"HelpFAQ_Cat_Presence_400_head": "Ger\u00e4te werden mit einer gelben Markierung und dem Hinweis \"missing Event\" angezeigt.",
"HelpFAQ_Cat_Presence_400_text": "Wenn dies geschieht hast du die M\u00f6glickeit, bei dem betreffenden Ger\u00e4t (Detailsansicht) die Events zu l\u00f6schen. Eine andere M\u00f6glichkeit w\u00e4re, das Ger\u00e4t einzuschalten und zu warten, bis NetAlertX mit dem n\u00e4chsten Scan das Ger\u00e4t als \"Online\" erkennt und anschlie\u00dfend das Ger\u00e4t einfach wieder ausschalten. Nun sollte NetAlertX mit dem n\u00e4chsten Scan den Zustand des Ger\u00e4tes ordentlich in der Datenbank vermerken.",
"HelpFAQ_Cat_Presence_401_head": "Ein Ger\u00e4t wird als Anwesend angezeigt, obwohl es \"Offline\" ist.",
"HelpFAQ_Cat_Presence_401_text": "Wenn dies geschieht hast du die M\u00f6glickeit, bei dem betreffenden Ger\u00e4t (Detailsansicht) die Events zu l\u00f6schen. Eine andere M\u00f6glichkeit w\u00e4re, das Ger\u00e4t einzuschalten und zu warten, bis NetAlertX mit dem n\u00e4chsten Scan das Ger\u00e4t als \"Online\" erkennt und anschlie\u00dfend das Ger\u00e4t einfach wieder ausschalten. Nun sollte NetAlertX mit dem n\u00e4chsten Scan den Zustand des Ger\u00e4tes ordentlich in der Datenbank vermerken.",
"HelpFAQ_Title": "Hilfe / FAQ",
"LOG_LEVEL_description": "Diese Einstellung aktiviert die erweiterte Protokollierung. Nützlich fürs Debuggen von in die Datenbank geschriebenen Events.",
"LOG_LEVEL_description": "Diese Einstellung aktiviert die erweiterte Protokollierung. N\u00fctzlich f\u00fcrs Debuggen von in die Datenbank geschriebenen Events.",
"LOG_LEVEL_name": "Erweiterte Protokollierung",
"Loading": "Laden...",
"Login_Box": "Passwort eingeben",
"Login_Default_PWD": "Standardpasswort \"123456\" noch immer aktiv.",
"Login_Psw-box": "Passwort",
"Login_Psw_alert": "Sicherheitshinweis!",
"Login_Psw_folder": "im Ordner ~/pialert/config",
"Login_Psw_folder": "im Ordner /app/config",
"Login_Psw_new": "neues_passwort",
"Login_Psw_run": "Um das Passwort zu ändern nutze:",
"Login_Psw_run": "Um das Passwort zu \u00e4ndern nutze:",
"Login_Remember": "Passwort speichern",
"Login_Remember_small": "(für 7 Tage gültig)",
"Login_Remember_small": "(f\u00fcr 7 Tage g\u00fcltig)",
"Login_Submit": "Anmelden",
"Login_Toggle_Alert_headline": "Passwort Warnung!",
"Login_Toggle_Info": "Passwort Informationen",
@@ -361,62 +371,64 @@
"Maintenance_Tool_ExportCSV": "CSV Export",
"Maintenance_Tool_ExportCSV_noti": "CSV Export",
"Maintenance_Tool_ExportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei erstellen wollen?",
"Maintenance_Tool_ExportCSV_text": "Generiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Dies kann auch durch das Besuchen dieser URL <code>your pialert url/php/server/devices.php?action=ExportCSV</code> ausgelöst werden.",
"Maintenance_Tool_ExportCSV_text": "Generiere eine CSV-Datei (comma separated values) mit einer Liste aller Ger\u00e4te und deren Beziehungen zwischen Netzwerkknoten und verbundenen Ger\u00e4ten. Dies kann auch durch das Besuchen dieser URL <code>your NetAlertX url/php/server/devices.php?action=ExportCSV</code> ausgel\u00f6st werden.",
"Maintenance_Tool_ImportCSV": "CSV Import",
"Maintenance_Tool_ImportCSV_noti": "CSV Import",
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird alle Geräte in der Datenbank überschreiben.",
"Maintenance_Tool_ImportCSV_text": "Machen Sie ein Backup, bevor Sie diese Funk­tion nutzen. Importiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Um dies zu tun platziere die <b>devices.csv</b> benannte CSV-Datei in deinen <b>/config</b> Ordner.",
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird alle Ger\u00e4te in der Datenbank \u00fcberschreiben.",
"Maintenance_Tool_ImportCSV_text": "Machen Sie ein Backup, bevor Sie diese Funk\u00adtion nutzen. Importiere eine CSV-Datei (comma separated values) mit einer Liste aller Ger\u00e4te und deren Beziehungen zwischen Netzwerkknoten und verbundenen Ger\u00e4ten. Um dies zu tun platziere die <b>devices.csv</b> benannte CSV-Datei in deinen <b>/config</b> Ordner.",
"Maintenance_Tool_arpscansw": "arp-Scan stoppen/starten",
"Maintenance_Tool_arpscansw_noti": "arp-Scan stoppen/starten",
"Maintenance_Tool_arpscansw_noti_text": "Wenn der Scan aus ist, bleibt er so lange aus bis er wieder aktiviert wird.",
"Maintenance_Tool_arpscansw_text": "Schaltet den arp-Scan an oder aus. Wenn der Scan aus ist, bleibt er so lange aus bis er wieder aktiviert wird. Bereits laufende Scans werden dabei nicht beendet.",
"Maintenance_Tool_backup": "DB Sicherung",
"Maintenance_Tool_backup_noti": "DB Sicherung",
"Maintenance_Tool_backup_noti_text": "Sind Sie sicher, dass Sie die Datenbank jetzt sichern möchten. Prüfen Sie, dass gerade keine Scans stattfinden.",
"Maintenance_Tool_backup_noti_text": "Sind Sie sicher, dass Sie die Datenbank jetzt sichern m\u00f6chten. Pr\u00fcfen Sie, dass gerade keine Scans stattfinden.",
"Maintenance_Tool_backup_text": "Die Datenbank-Sicher&shy;ungen befinden sich im Datenbank-Ver&shy;zeich&shy;nis, gepackt als zip-Archive, benannt mit dem Erstellungs&shy;datum. Es gibt keine maximale Anzahl von Backups.",
"Maintenance_Tool_check_visible": "Abwählen um die Spalte auszublenden.",
"Maintenance_Tool_check_visible": "Abw\u00e4hlen um die Spalte auszublenden.",
"Maintenance_Tool_darkmode": "Darstellungswechsel (Dunkel/Hell)",
"Maintenance_Tool_darkmode_noti": "Darstellungswechsel",
"Maintenance_Tool_darkmode_noti_text": "Wechselt zwischen der hellen und der dunklen Darstellung. Wenn die Umschaltung nicht ordentlich funktionieren sollte, versuchen Sie den Browsercache zu löschen.",
"Maintenance_Tool_darkmode_text": "Wechselt zwischen der hellen und der dunklen Darstellung. Wenn der Wechsel nicht richtig funktionieren sollte, versuchen Sie den Browsercache zu löschen. Die Änderung findet serverseitig statt, betrifft also alle verwendeten Geräte.",
"Maintenance_Tool_del_ActHistory": "Löschen der Netzwerkaktivität",
"Maintenance_Tool_del_ActHistory_noti": "Netzwerkaktivität löschen",
"Maintenance_Tool_del_ActHistory_noti_text": "Sind Sie sicher, dass Sie die Netzwerkaktivität zurücksetzen möchten?",
"Maintenance_Tool_del_ActHistory_text": "Der Graph für die Netzwerkaktivität wird zurückgesetzt. Hierbei werden die Events nicht beeinflusst.",
"Maintenance_Tool_del_alldev": "Alle Geräte löschen",
"Maintenance_Tool_del_alldev_noti": "Geräte löschen",
"Maintenance_Tool_del_alldev_noti_text": "Sind Sie sich sicher, dass Sie alle Geräte löschen wollen?",
"Maintenance_Tool_del_alldev_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht rück&shy;gängig gemacht werden. Alle Geräte werden in der Datenbank ge&shy;löscht.",
"Maintenance_Tool_del_allevents": "Alle Ereignisse löschen",
"Maintenance_Tool_del_allevents30": "Alle Ereignisse älter als 30 Tage löschen",
"Maintenance_Tool_del_allevents30_noti": "Ereignisse löschen",
"Maintenance_Tool_del_allevents30_noti_text": "Sind Sie sich sicher, dass Sie alle Ereignisse älter als 30 Tage löschen wollen? Dies setzt die Präsenz aller Geräte zurück.",
"Maintenance_Tool_del_allevents30_text": "Machen Sie ein Backup, bevor Sie diese Funk­tion nutzen. Der Vor­gang kann ohne Back­up nicht rück­ngig gemacht werden. Alle Ereignisse älter als 30 Tage werden aus der Datenbank ge­scht. Dies setzt auch die Anwesenheit zu­ck. Es kann ab dem Moment zu ungültigen Sitzungen kommen. Ein Scan, während das betreffende Gerät online ist, sollte das Problem lösen.",
"Maintenance_Tool_del_allevents_noti": "Alle Ereignisse löschen",
"Maintenance_Tool_del_allevents_noti_text": "Sind Sie sicher, dass Sie alle Ereignisse aus der Datenbank löschen wollen. Dies setzt die Anwesenheit aller Geräte zurück.",
"Maintenance_Tool_del_allevents_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht rück&shy;gängig gemacht werden. Alle Ereignisse werden aus der Datenbank ge&shy;löscht. Dies setzt auch die Anwesenheit zu&shy;rück. Es kann ab dem Moment zu ungültigen Sitzungen kommen. Ein Scan, während das betreffende Gerät online ist, sollte das Problem lösen.",
"Maintenance_Tool_del_empty_macs": "Alle Geräte ohne MAC löschen",
"Maintenance_Tool_del_empty_macs_noti": "Geräte löschen",
"Maintenance_Tool_del_empty_macs_noti_text": "Sind Sie sicher, dass Sie alle Geräte ohne MAC-Adresse löschen wollen?<br>(Vielleicht bevorzugen Sie eine Archivierung)",
"Maintenance_Tool_del_empty_macs_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht rück&shy;gängig gemacht werden. Alle Geäte ohne MAC-Adresse werden aus der Datenbank ge&shy;löscht.",
"Maintenance_Tool_del_unknowndev": "Löschen der (unknown) Geräte",
"Maintenance_Tool_del_unknowndev_noti": "Lösche (unknown) Geräte",
"Maintenance_Tool_del_unknowndev_noti_text": "Sind Sie sicher, dass Sie alle (unknown) Geräte aus der Datenbank löschen wollen?",
"Maintenance_Tool_del_unknowndev_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht rück&shy;gängig gemacht werden. Alle Gräte mit dem Namen (unknown) werden aus der Datenbank ge&shy;löscht.",
"Maintenance_Tool_displayed_columns_text": "Ändere die Sichtbarkeit und Anordnung der Spalten in der <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Geräte</b></a>-Seite. (Drag-and-Drop funktioniert nicht einwandfrei, ist aber verwendbar. Ich habe <a href=\"https://github.com/jokob-sk/Pi.Alert/commit/94b32f0f7332879f5a7d2af05dafa2e5d5cfa5da\">3 Stunden</a> versucht das zu beheben, werde es aber nicht weiter verfolgen. Über einen PR mit einem Fix würde ich mich freuen :) ).",
"Maintenance_Tool_drag_me": "Zieh mich um die Anordnung der Spalten zu ändern.",
"Maintenance_Tool_darkmode_noti_text": "Wechselt zwischen der hellen und der dunklen Darstellung. Wenn die Umschaltung nicht ordentlich funktionieren sollte, versuchen Sie den Browsercache zu l\u00f6schen.",
"Maintenance_Tool_darkmode_text": "Wechselt zwischen der hellen und der dunklen Darstellung. Wenn der Wechsel nicht richtig funktionieren sollte, versuchen Sie den Browsercache zu l\u00f6schen. Die \u00c4nderung findet serverseitig statt, betrifft also alle verwendeten Ger\u00e4te.",
"Maintenance_Tool_del_ActHistory": "L\u00f6schen der Netzwerkaktivit\u00e4t",
"Maintenance_Tool_del_ActHistory_noti": "Netzwerkaktivit\u00e4t l\u00f6schen",
"Maintenance_Tool_del_ActHistory_noti_text": "Sind Sie sicher, dass Sie die Netzwerkaktivit\u00e4t zur\u00fccksetzen m\u00f6chten?",
"Maintenance_Tool_del_ActHistory_text": "Der Graph f\u00fcr die Netzwerkaktivit\u00e4t wird zur\u00fcckgesetzt. Hierbei werden die Events nicht beeinflusst.",
"Maintenance_Tool_del_alldev": "Alle Ger\u00e4te l\u00f6schen",
"Maintenance_Tool_del_alldev_noti": "Ger\u00e4te l\u00f6schen",
"Maintenance_Tool_del_alldev_noti_text": "Sind Sie sich sicher, dass Sie alle Ger\u00e4te l\u00f6schen wollen?",
"Maintenance_Tool_del_alldev_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht r\u00fcck&shy;g\u00e4ngig gemacht werden. Alle Ger\u00e4te werden in der Datenbank ge&shy;l\u00f6scht.",
"Maintenance_Tool_del_allevents": "Alle Ereignisse l\u00f6schen",
"Maintenance_Tool_del_allevents30": "Alle Ereignisse \u00e4lter als 30 Tage l\u00f6schen",
"Maintenance_Tool_del_allevents30_noti": "Ereignisse l\u00f6schen",
"Maintenance_Tool_del_allevents30_noti_text": "Sind Sie sich sicher, dass Sie alle Ereignisse \u00e4lter als 30 Tage l\u00f6schen wollen? Dies setzt die Pr\u00e4senz aller Ger\u00e4te zur\u00fcck.",
"Maintenance_Tool_del_allevents30_text": "Machen Sie ein Backup, bevor Sie diese Funk\u00adtion nutzen. Der Vor\u00adgang kann ohne Back\u00adup nicht r\u00fcck\u00adg\u00e4ngig gemacht werden. Alle Ereignisse \u00e4lter als 30 Tage werden aus der Datenbank ge\u00adl\u00f6scht. Dies setzt auch die Anwesenheit zu\u00adr\u00fcck. Es kann ab dem Moment zu ung\u00fcltigen Sitzungen kommen. Ein Scan, w\u00e4hrend das betreffende Ger\u00e4t online ist, sollte das Problem l\u00f6sen.",
"Maintenance_Tool_del_allevents_noti": "Alle Ereignisse l\u00f6schen",
"Maintenance_Tool_del_allevents_noti_text": "Sind Sie sicher, dass Sie alle Ereignisse aus der Datenbank l\u00f6schen wollen. Dies setzt die Anwesenheit aller Ger\u00e4te zur\u00fcck.",
"Maintenance_Tool_del_allevents_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht r\u00fcck&shy;g\u00e4ngig gemacht werden. Alle Ereignisse werden aus der Datenbank ge&shy;l\u00f6scht. Dies setzt auch die Anwesenheit zu&shy;r\u00fcck. Es kann ab dem Moment zu ung\u00fcltigen Sitzungen kommen. Ein Scan, w\u00e4hrend das betreffende Ger\u00e4t online ist, sollte das Problem l\u00f6sen.",
"Maintenance_Tool_del_empty_macs": "Alle Ger\u00e4te ohne MAC l\u00f6schen",
"Maintenance_Tool_del_empty_macs_noti": "Ger\u00e4te l\u00f6schen",
"Maintenance_Tool_del_empty_macs_noti_text": "Sind Sie sicher, dass Sie alle Ger\u00e4te ohne MAC-Adresse l\u00f6schen wollen?<br>(Vielleicht bevorzugen Sie eine Archivierung)",
"Maintenance_Tool_del_empty_macs_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht r\u00fcck&shy;g\u00e4ngig gemacht werden. Alle Ge\u00e4te ohne MAC-Adresse werden aus der Datenbank ge&shy;l\u00f6scht.",
"Maintenance_Tool_del_selecteddev": "",
"Maintenance_Tool_del_selecteddev_text": "",
"Maintenance_Tool_del_unknowndev": "L\u00f6schen der (unknown) Ger\u00e4te",
"Maintenance_Tool_del_unknowndev_noti": "L\u00f6sche (unknown) Ger\u00e4te",
"Maintenance_Tool_del_unknowndev_noti_text": "Sind Sie sicher, dass Sie alle (unknown) Ger\u00e4te aus der Datenbank l\u00f6schen wollen?",
"Maintenance_Tool_del_unknowndev_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen. Der Vor&shy;gang kann ohne Back&shy;up nicht r\u00fcck&shy;g\u00e4ngig gemacht werden. Alle Gr\u00e4te mit dem Namen (unknown) werden aus der Datenbank ge&shy;l\u00f6scht.",
"Maintenance_Tool_displayed_columns_text": "\u00c4ndere die Sichtbarkeit und Anordnung der Spalten in der <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Ger\u00e4te</b></a>-Seite. (Drag-and-Drop funktioniert nicht einwandfrei, ist aber verwendbar. Ich habe <a href=\"https://github.com/jokob-sk/NetAlertX/commit/94b32f0f7332879f5a7d2af05dafa2e5d5cfa5da\">3 Stunden</a> versucht das zu beheben, werde es aber nicht weiter verfolgen. \u00dcber einen PR mit einem Fix w\u00fcrde ich mich freuen :) ).",
"Maintenance_Tool_drag_me": "Zieh mich um die Anordnung der Spalten zu \u00e4ndern.",
"Maintenance_Tool_order_columns_text": "",
"Maintenance_Tool_purgebackup": "Sicherungen aufräumen",
"Maintenance_Tool_purgebackup_noti": "Sicherungen aufräumen",
"Maintenance_Tool_purgebackup_noti_text": "Sind Sie sicher, alle Backups, bis auf die letzten 3 löschen möchten?",
"Maintenance_Tool_purgebackup_text": "Es werden, bis auf die letzten 3 Backups, alle übrigen Backups gelöscht.",
"Maintenance_Tool_purgebackup": "Sicherungen aufr\u00e4umen",
"Maintenance_Tool_purgebackup_noti": "Sicherungen aufr\u00e4umen",
"Maintenance_Tool_purgebackup_noti_text": "Sind Sie sicher, alle Backups, bis auf die letzten 3 l\u00f6schen m\u00f6chten?",
"Maintenance_Tool_purgebackup_text": "Es werden, bis auf die letzten 3 Backups, alle \u00fcbrigen Backups gel\u00f6scht.",
"Maintenance_Tool_restore": "DB Wiederherstellung",
"Maintenance_Tool_restore_noti": "DB Wiederherstellung",
"Maintenance_Tool_restore_noti_text": "Sind Sie sicher, dass Sie die Datenbank aus der neusten Sicherung wiederherstellen möchten? Prüfen Sie, dass gerade keine Scans stattfinden.",
"Maintenance_Tool_restore_text": "Das neuste Backup kann über diese Funk&shy;tion wiederhergestellt werden. Ältere Sicher&shy;ungen müssen manuell wieder&shy;hergestellt wer&shy;den. Es empfiehlt sich eine Integritäts&shy;prüfung nach der Wieder&shy;her&shy;stellung zu machen, falls die Datenbank bei der Sicherung geöffnet war.",
"Maintenance_Tool_restore_noti_text": "Sind Sie sicher, dass Sie die Datenbank aus der neusten Sicherung wiederherstellen m\u00f6chten? Pr\u00fcfen Sie, dass gerade keine Scans stattfinden.",
"Maintenance_Tool_restore_text": "Das neuste Backup kann \u00fcber diese Funk&shy;tion wiederhergestellt werden. \u00c4ltere Sicher&shy;ungen m\u00fcssen manuell wieder&shy;hergestellt wer&shy;den. Es empfiehlt sich eine Integrit\u00e4ts&shy;pr\u00fcfung nach der Wieder&shy;her&shy;stellung zu machen, falls die Datenbank bei der Sicherung ge\u00f6ffnet war.",
"Maintenance_Tool_upgrade_database_noti": "Aktualisiere Datenbank",
"Maintenance_Tool_upgrade_database_noti_text": "Machen Sie ein Backup, bevor Sie diese Funk&shy;tion nutzen.",
"Maintenance_Tool_upgrade_database_text": "Mit dieser Schaltfläche wird die Datenbank aktualisiert, um das Diagramm der Netzwerkaktivitäten der letzten 12 Stunden zu aktivieren. Bitte sichern Sie Ihre Datenbank, falls Probleme auftreten.",
"Maintenance_Tool_upgrade_database_text": "Mit dieser Schaltfl\u00e4che wird die Datenbank aktualisiert, um das Diagramm der Netzwerkaktivit\u00e4ten der letzten 12 Stunden zu aktivieren. Bitte sichern Sie Ihre Datenbank, falls Probleme auftreten.",
"Maintenance_Tools_Tab_BackupRestore": "Sicherg. / Wiederherstellg.",
"Maintenance_Tools_Tab_Logging": "Logs",
"Maintenance_Tools_Tab_Settings": "Einstellungen",
@@ -426,29 +438,26 @@
"Maintenance_arp_status_off": "ist im Moment deaktiviert",
"Maintenance_arp_status_on": "Scan(s) sind gerade aktiv",
"Maintenance_built_on": "Erstellt am",
"Maintenance_current_version": "Du bist up-to-date. Sieh dir an, <a href=\"https://github.com/jokob-sk/Pi.Alert/issues/138\" target=\"_blank\">woran ich gerade arbeite</a>.",
"Maintenance_current_version": "Du bist up-to-date. Sieh dir an, <a href=\"https://github.com/jokob-sk/NetAlertX/issues/138\" target=\"_blank\">woran ich gerade arbeite</a>.",
"Maintenance_database_backup": "DB Sicherungen",
"Maintenance_database_backup_found": "Sicherungen verfügbar",
"Maintenance_database_backup_found": "Sicherungen verf\u00fcgbar",
"Maintenance_database_backup_total": "Speicherplatz insgesamt",
"Maintenance_database_lastmod": "Letzte Änderung",
"Maintenance_database_lastmod": "Letzte \u00c4nderung",
"Maintenance_database_path": "Datenbank-Pfad",
"Maintenance_database_rows": "Tabelle (Reihen)",
"Maintenance_database_size": "Datenbank-Größe",
"Maintenance_lang_de_de": "Deutsch (DE)",
"Maintenance_lang_en_us": "Englisch (US)",
"Maintenance_lang_es_es": "Spanisch (ES)",
"Maintenance_lang_selector_apply": "Übernehmen",
"Maintenance_lang_selector_empty": "Sprache wählen",
"Maintenance_database_size": "Datenbank-Gr\u00f6\u00dfe",
"Maintenance_lang_selector_apply": "\u00dcbernehmen",
"Maintenance_lang_selector_empty": "Sprache w\u00e4hlen",
"Maintenance_lang_selector_lable": "Sprachauswahl",
"Maintenance_lang_selector_text": "Die Änderung findet serverseitig statt, betrifft also alle verwendeten Geräte.",
"Maintenance_new_version": "🆕 Eine neue Version ist vefügbar. Sieh dir die <a href=\"https://github.com/jokob-sk/Pi.Alert/releases\" target=\"_blank\">Versionshinweise</a> an.",
"Maintenance_themeselector_apply": "Übernehmen",
"Maintenance_themeselector_empty": "Skin wählen",
"Maintenance_lang_selector_text": "Die \u00c4nderung findet serverseitig statt, betrifft also alle verwendeten Ger\u00e4te.",
"Maintenance_new_version": "\ud83c\udd95 Eine neue Version ist vef\u00fcgbar. Sieh dir die <a href=\"https://github.com/jokob-sk/NetAlertX/releases\" target=\"_blank\">Versionshinweise</a> an.",
"Maintenance_themeselector_apply": "\u00dcbernehmen",
"Maintenance_themeselector_empty": "Skin w\u00e4hlen",
"Maintenance_themeselector_lable": "Skin Auswahl",
"Maintenance_themeselector_text": "Die Änderung findet serverseitig statt, betrifft also alle verwendeten Geräte.",
"Maintenance_themeselector_text": "Die \u00c4nderung findet serverseitig statt, betrifft also alle verwendeten Ger\u00e4te.",
"Maintenance_version": "App Updates",
"NETWORK_DEVICE_TYPES_description": "Welche Gerätetypen als Netzwerkgeräte in der Netzwerkansicht verwendet werden können. Der Gerätetyp muss genau der <code>Typ</code>-Einstellung eines spezifischen Geräts in den Gerätedetails übereinstimmen. Entfernen Sie keine existierenden Typen, sondern fügen Sie nur neue ein.",
"NETWORK_DEVICE_TYPES_name": "Netzwerkgeräte-Typen",
"NETWORK_DEVICE_TYPES_description": "Welche Ger\u00e4tetypen als Netzwerkger\u00e4te in der Netzwerkansicht verwendet werden k\u00f6nnen. Der Ger\u00e4tetyp muss genau der <code>Typ</code>-Einstellung eines spezifischen Ger\u00e4ts in den Ger\u00e4tedetails \u00fcbereinstimmen. Entfernen Sie keine existierenden Typen, sondern f\u00fcgen Sie nur neue ein.",
"NETWORK_DEVICE_TYPES_name": "Netzwerkger\u00e4te-Typen",
"NTFY_HOST_description": "NTFY host URL starting with <code>http://</code> or <code>https://</code>. You can use the hosted instance on <a target=\"_blank\" href=\"https://ntfy.sh/\">https://ntfy.sh</a> by simply entering <code>https://ntfy.sh</code>.",
"NTFY_HOST_name": "NTFY host URL",
"NTFY_PASSWORD_description": "Enter password if you need (host) an instance with enabled authetication.",
@@ -459,12 +468,15 @@
"NTFY_USER_name": "NTFY user",
"NTFY_display_name": "NTFY",
"NTFY_icon": "<i class=\"fa fa-terminal\"></i>",
"Navigation_Devices": "Geräte",
"Navigation_About": "",
"Navigation_Devices": "Ger\u00e4te",
"Navigation_Donations": "Donations",
"Navigation_Events": "Ereignisse",
"Navigation_Flows": "Flows",
"Navigation_HelpFAQ": "Hilfe / FAQ",
"Navigation_Integrations": "",
"Navigation_Maintenance": "Wartung",
"Navigation_Monitoring": "",
"Navigation_Network": "Netzwerk",
"Navigation_Plugins": "Plugins",
"Navigation_Presence": "Anwesenheit",
@@ -473,53 +485,53 @@
"Navigation_SystemInfo": "Systeminfo",
"Navigation_Workflows": "",
"Network_Assign": "Zum obigen <i class=\"fa fa-server\"></i> Netzwerkknoten zuweisen",
"Network_Cant_Assign": "Internet-Wurzelknoten kann nicht als äußerer Kindknoten zugewiesen werden.",
"Network_Cant_Assign": "Internet-Wurzelknoten kann nicht als \u00e4u\u00dferer Kindknoten zugewiesen werden.",
"Network_Configuration_Error": "",
"Network_Connected": "Verbundene Geräte",
"Network_ManageAdd": "Gerät hinzufügen",
"Network_ManageAdd_Name": "Name des Gerätes",
"Network_Connected": "Verbundene Ger\u00e4te",
"Network_ManageAdd": "Ger\u00e4t hinzuf\u00fcgen",
"Network_ManageAdd_Name": "Name des Ger\u00e4tes",
"Network_ManageAdd_Name_text": "Name ohne Sonderzeichen",
"Network_ManageAdd_Port": "Portanzahl",
"Network_ManageAdd_Port_text": "bei WLAN oder Powerline leer lassen",
"Network_ManageAdd_Submit": "Hinzufügen",
"Network_ManageAdd_Type": "Gerätetyp",
"Network_ManageAdd_Type_text": "-- Typ wählen --",
"Network_ManageAdd_Submit": "Hinzuf\u00fcgen",
"Network_ManageAdd_Type": "Ger\u00e4tetyp",
"Network_ManageAdd_Type_text": "-- Typ w\u00e4hlen --",
"Network_ManageAssign": "Zuweisen",
"Network_ManageDel": "Gerät löschen",
"Network_ManageDel_Name": "Gerät zum Löschen auswählen",
"Network_ManageDel_Name_text": "-- Gerät wählen --",
"Network_ManageDel_Submit": "Löschen",
"Network_ManageDevices": "Geräte verwalten",
"Network_ManageEdit": "Gerät bearbeiten",
"Network_ManageEdit_ID": "Gerät zum Bearbeiten auswählen",
"Network_ManageEdit_ID_text": "-- Gerät wählen --",
"Network_ManageDel": "Ger\u00e4t l\u00f6schen",
"Network_ManageDel_Name": "Ger\u00e4t zum L\u00f6schen ausw\u00e4hlen",
"Network_ManageDel_Name_text": "-- Ger\u00e4t w\u00e4hlen --",
"Network_ManageDel_Submit": "L\u00f6schen",
"Network_ManageDevices": "Ger\u00e4te verwalten",
"Network_ManageEdit": "Ger\u00e4t bearbeiten",
"Network_ManageEdit_ID": "Ger\u00e4t zum Bearbeiten ausw\u00e4hlen",
"Network_ManageEdit_ID_text": "-- Ger\u00e4t w\u00e4hlen --",
"Network_ManageEdit_Name": "Neuer Name",
"Network_ManageEdit_Name_text": "Name ohne Sonderzeichen",
"Network_ManageEdit_Port": "Neue Portanzahl",
"Network_ManageEdit_Port_text": "bei WLAN oder Powerline leer lassen",
"Network_ManageEdit_Submit": "Speichern",
"Network_ManageEdit_Type": "Neuer Typ",
"Network_ManageEdit_Type_text": "-- Typ wählen --",
"Network_ManageEdit_Type_text": "-- Typ w\u00e4hlen --",
"Network_ManageLeaf": "Zuweisungen verwalten",
"Network_ManageUnassign": "Zuweisung aufheben",
"Network_NoAssignedDevices": "Dieser Netzwerkknoten hat keine zugewiesenen Geräte (Kindknoten). Weise eins von unten zu oder gehe in den <b><i class=\"fa fa-info-circle\"></i> Details</b> Tab eines Gerätes in <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Geräte</b></a>, und weise dort das Gerät einem <b><i class=\"fa fa-server\"></i> Netzwerk Knoten</b> und einem <b><i class=\"fa fa-ethernet\"></i> Netzwerk Knoten Port</b> zu.",
"Network_NoAssignedDevices": "Dieser Netzwerkknoten hat keine zugewiesenen Ger\u00e4te (Kindknoten). Weise eins von unten zu oder gehe in den <b><i class=\"fa fa-info-circle\"></i> Details</b> Tab eines Ger\u00e4tes in <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Ger\u00e4te</b></a>, und weise dort das Ger\u00e4t einem <b><i class=\"fa fa-server\"></i> Netzwerk Knoten</b> und einem <b><i class=\"fa fa-ethernet\"></i> Netzwerk Knoten Port</b> zu.",
"Network_NoDevices": "",
"Network_Node": "Netzwerkknoten",
"Network_Node_Name": "Knotenname",
"Network_Parent": "Übergeordnetes Netzwerkgerät",
"Network_Parent": "\u00dcbergeordnetes Netzwerkger\u00e4t",
"Network_Root": "",
"Network_Root_Not_Configured": "",
"Network_Root_Unconfigurable": "Nicht konfigurierbare Wurzel",
"Network_Table_Hostname": "Gerätename",
"Network_Table_Hostname": "Ger\u00e4tename",
"Network_Table_IP": "IP",
"Network_Table_State": "Status",
"Network_Title": "Netzwerkübersicht",
"Network_UnassignedDevices": "Nicht zugewiesene Geräte",
"PIALERT_WEB_PASSWORD_description": "Das Standardpasswort ist <code>123456</code>. Um das Passwort zu ändern, entweder <code>/home/pi/pialert/back/pialert-cli</code> im Container starten oder <a onclick=\"toggleAllSettings()\" href=\"#SETPWD_RUN\"><code>SETPWD_RUN</code> Set password plugin</a> nutzen.",
"Network_Title": "Netzwerk\u00fcbersicht",
"Network_UnassignedDevices": "Nicht zugewiesene Ger\u00e4te",
"PIALERT_WEB_PASSWORD_description": "Das Standardpasswort ist <code>123456</code>. Um das Passwort zu \u00e4ndern, entweder <code>/app/back/pialert-cli</code> im Container starten oder <a onclick=\"toggleAllSettings()\" href=\"#SETPWD_RUN\"><code>SETPWD_RUN</code> Set password plugin</a> nutzen.",
"PIALERT_WEB_PASSWORD_name": "Login-Passwort",
"PIALERT_WEB_PROTECTION_description": "Ein Loginfenster wird angezeigt wenn aktiviert. Untere Beschreibung genau durchlesen falls Sie sich aus Ihrer Instanz aussperren.",
"PIALERT_WEB_PROTECTION_name": "Login aktivieren",
"PLUGINS_KEEP_HIST_description": "Wie viele Plugin Scanresultate behalten werden (pro Plugin, nicht gerätespezifisch).",
"PLUGINS_KEEP_HIST_description": "Wie viele Plugin Scanresultate behalten werden (pro Plugin, nicht ger\u00e4tespezifisch).",
"PLUGINS_KEEP_HIST_name": "Plugins Verlauf",
"PUSHSAFER_TOKEN_description": "Your secret Pushsafer API key (token).",
"PUSHSAFER_TOKEN_name": "Pushsafer token",
@@ -538,21 +550,21 @@
"Presence_CalHead_quarter": "Quartal",
"Presence_CalHead_week": "Woche",
"Presence_CalHead_year": "Jahr",
"Presence_CallHead_Devices": "Geräte",
"Presence_CallHead_Devices": "Ger\u00e4te",
"Presence_Loading": "Laden...",
"Presence_Shortcut_AllDevices": "Alle Geräte",
"Presence_Shortcut_AllDevices": "Alle Ger\u00e4te",
"Presence_Shortcut_Archived": "Archiviert",
"Presence_Shortcut_Connected": "Verbunden",
"Presence_Shortcut_Devices": "Geräte",
"Presence_Shortcut_Devices": "Ger\u00e4te",
"Presence_Shortcut_DownAlerts": "Down Meldungen",
"Presence_Shortcut_Favorites": "Favoriten",
"Presence_Shortcut_NewDevices": "Neue Geräte",
"Presence_Title": "Anwesenheit pro Gerät",
"Presence_Shortcut_NewDevices": "Neue Ger\u00e4te",
"Presence_Title": "Anwesenheit pro Ger\u00e4t",
"REPORT_APPRISE_description": "Enable sending notifications via <a target=\"_blank\" href=\"https://hub.docker.com/r/caronc/apprise\">Apprise</a>.",
"REPORT_APPRISE_name": "Enable Apprise",
"REPORT_DASHBOARD_URL_description": "Diese URL wird als Basis fürs Erstellen von Links in E-Mails genutzt. Geben Sie die gesamte URL startend mit <code>http://</code> inklusive der genutzten Portnummer ein (keinen nachfolgenden Schrägstrich <code>/</code> nutzen).",
"REPORT_DASHBOARD_URL_name": "Pi.Alert URL",
"REPORT_ERROR": "Die gesuchte Seite ist vorübergehend nicht verfügbar. Bitte versuchen Sie es nach ein paar Sekunden erneut",
"REPORT_DASHBOARD_URL_description": "Diese URL wird als Basis f\u00fcrs Erstellen von Links in E-Mails genutzt. Geben Sie die gesamte URL startend mit <code>http://</code> inklusive der genutzten Portnummer ein (keinen nachfolgenden Schr\u00e4gstrich <code>/</code> nutzen).",
"REPORT_DASHBOARD_URL_name": "NetAlertX URL",
"REPORT_ERROR": "Die gesuchte Seite ist vor\u00fcbergehend nicht verf\u00fcgbar. Bitte versuchen Sie es nach ein paar Sekunden erneut",
"REPORT_FROM_description": "Notification email subject line. Some SMTP servers need this to be an email.",
"REPORT_FROM_name": "Email subject",
"REPORT_MAIL_description": "If enabled an email is sent out with a list of changes you nove subscribed to. Please also fill out all remaining settings related to the SMTP setup below. If facing issues, set <code>LOG_LEVEL</code> to <code>debug</code> and check the <a href=\"/maintenance.php#tab_Logging\">error log</a>.",
@@ -566,17 +578,17 @@
"REPORT_TITLE": "Bericht",
"REPORT_TO_description": "Email address to which the notification will be send to.",
"REPORT_TO_name": "Send email to",
"REPORT_WEBHOOK_description": "Enable webhooks for notifications. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href=\"https://n8n.io/\" target=\"_blank\">n8n</a> to name a few. Check out this simple <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md\" target=\"_blank\">n8n guide here</a> to get started. If enabled, configure related settings below.",
"REPORT_WEBHOOK_description": "Enable webhooks for notifications. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href=\"https://n8n.io/\" target=\"_blank\">n8n</a> to name a few. Check out this simple <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md\" target=\"_blank\">n8n guide here</a> to get started. If enabled, configure related settings below.",
"REPORT_WEBHOOK_name": "Enable Webhooks",
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.",
"SCAN_SUBNETS_description": "Arp-scan is a command-line tool that uses the ARP protocol to discover and fingerprint IP hosts on the local network. An alternative to ARP scan is to enable the <a onclick=\"toggleAllSettings()\" href=\"#PIHOLE_RUN\"><code>PIHOLE_RUN</code>PiHole integration settings</a>. The arp-scan time itself depends on the number of IP addresses to check so set this up carefully with the appropriate network mask and interface. Check the <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on setting up VLANs, what VLANs are supported, or how to figure out the network mask and your interface.",
"SCAN_SUBNETS_description": "Arp-scan is a command-line tool that uses the ARP protocol to discover and fingerprint IP hosts on the local network. An alternative to ARP scan is to enable the <a onclick=\"toggleAllSettings()\" href=\"#PIHOLE_RUN\"><code>PIHOLE_RUN</code>PiHole integration settings</a>. The arp-scan time itself depends on the number of IP addresses to check so set this up carefully with the appropriate network mask and interface. Check the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on setting up VLANs, what VLANs are supported, or how to figure out the network mask and your interface.",
"SMTP_FORCE_SSL_description": "Force SSL when connecting to your SMTP server.",
"SMTP_FORCE_SSL_name": "Force SSL",
"SMTP_PASS_description": "The SMTP server password. ",
"SMTP_PASS_name": "SMTP password",
"SMTP_PORT_description": "Port number used for the SMTP connection. Set to <code>0</code> if you do not want to use a port when connecting to the SMTP server.",
"SMTP_PORT_name": "SMTP server PORT",
"SMTP_SERVER_description": "The SMTP server host URL. For example <code>smtp-relay.sendinblue.com</code>. To use Gmail as an SMTP server <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SMTP.md\">follow this guide</a>",
"SMTP_SERVER_description": "The SMTP server host URL. For example <code>smtp-relay.sendinblue.com</code>. To use Gmail as an SMTP server <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SMTP.md\">follow this guide</a>",
"SMTP_SERVER_name": "SMTP server URL",
"SMTP_SKIP_LOGIN_description": "Do not use authentication when connecting to the SMTP server.",
"SMTP_SKIP_LOGIN_name": "Skip authentication",
@@ -597,12 +609,12 @@
"Systeminfo_CPU_Speed": "CPU-Geschwindigkeit:",
"Systeminfo_CPU_Temp": "CPU-Temp:",
"Systeminfo_CPU_Vendor": "CPU-Anbieter:",
"Systeminfo_Client_Resolution": "Browserauflösung:",
"Systeminfo_Client_Resolution": "Browseraufl\u00f6sung:",
"Systeminfo_Client_User_Agent": "Browser-Bezeichnung:",
"Systeminfo_General": "Allgemein",
"Systeminfo_General_Date": "Datum:",
"Systeminfo_General_Date2": "Datum2:",
"Systeminfo_General_Full_Date": "Vollständiges Datum:",
"Systeminfo_General_Full_Date": "Vollst\u00e4ndiges Datum:",
"Systeminfo_General_TimeZone": "Zeitzone:",
"Systeminfo_Memory": "Arbeitsspeicher",
"Systeminfo_Memory_Total_Memory": "Gesamtspeicher:",
@@ -623,6 +635,10 @@
"Systeminfo_Network_HTTP_Referer": "HTTP-Referer:",
"Systeminfo_Network_HTTP_Referer_String": "Kein HTTP-Referer",
"Systeminfo_Network_Hardware": "Netzwerk Hardware",
"Systeminfo_Network_Hardware_Interface_Mask": "",
"Systeminfo_Network_Hardware_Interface_Name": "",
"Systeminfo_Network_Hardware_Interface_RX": "",
"Systeminfo_Network_Hardware_Interface_TX": "",
"Systeminfo_Network_IP": "IP Internet:",
"Systeminfo_Network_IP_Connection": "IP-Verbindung:",
"Systeminfo_Network_IP_Server": "Server-IP:",
@@ -641,9 +657,9 @@
"Systeminfo_Services_Description": "Dienstbeschreibung",
"Systeminfo_Services_Name": "Dienstname",
"Systeminfo_Storage": "Speicher",
"Systeminfo_Storage_Device": "Gerät:",
"Systeminfo_Storage_Device": "Ger\u00e4t:",
"Systeminfo_Storage_Mount": "Mountpunkt:",
"Systeminfo_Storage_Size": "Größe:",
"Systeminfo_Storage_Size": "Gr\u00f6\u00dfe:",
"Systeminfo_Storage_Type": "Typ:",
"Systeminfo_Storage_Usage": "Speicherverwendung",
"Systeminfo_Storage_Usage_Free": "Frei:",
@@ -659,23 +675,30 @@
"Systeminfo_System_System": "System:",
"Systeminfo_System_Uname": "Uname:",
"Systeminfo_System_Uptime": "Betriebszeit:",
"Systeminfo_This_Client": "Dieses Gerät",
"Systeminfo_USB_Devices": "USB-Geräte",
"Systeminfo_This_Client": "Dieses Ger\u00e4t",
"Systeminfo_USB_Devices": "USB-Ger\u00e4te",
"TICKER_MIGRATE_TO_NETALERTX": "",
"TIMEZONE_description": "Zeitzone um Statistiken korrekt darzustellen. Finde deine Zeitzone <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">hier</a>.",
"TIMEZONE_name": "Zeitzone",
"UI_LANG_description": "Bevorzugte Oberflächensprache auswählen.",
"UI_DEV_SECTIONS_description": "",
"UI_DEV_SECTIONS_name": "",
"UI_ICONS_description": "",
"UI_ICONS_name": "",
"UI_LANG_description": "Bevorzugte Oberfl\u00e4chensprache ausw\u00e4hlen.",
"UI_LANG_name": "UI Sprache",
"UI_MY_DEVICES_description": "",
"UI_MY_DEVICES_name": "",
"UI_NOT_RANDOM_MAC_description": "",
"UI_NOT_RANDOM_MAC_name": "",
"UI_PRESENCE_description": "Auswählen, welche Status im <b>Gerätepräsenz im Laufe der Zeit</b>-Diagramm in der <a href=\"/devices.php\" target=\"_blank\">Geräte</a>-Seite angzeigt werden sollen. (<code>STRG + klicken</code> zum aus-/abwählen).",
"UI_PRESENCE_name": "Anzeige im Präsenzdiagramm",
"WEBHOOK_PAYLOAD_description": "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)",
"UI_PRESENCE_description": "Ausw\u00e4hlen, welche Status im <b>Ger\u00e4tepr\u00e4senz im Laufe der Zeit</b>-Diagramm in der <a href=\"/devices.php\" target=\"_blank\">Ger\u00e4te</a>-Seite angzeigt werden sollen. (<code>STRG + klicken</code> zum aus-/abw\u00e4hlen).",
"UI_PRESENCE_name": "Anzeige im Pr\u00e4senzdiagramm",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"WEBHOOK_PAYLOAD_description": "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)",
"WEBHOOK_PAYLOAD_name": "Payload type",
"WEBHOOK_REQUEST_METHOD_description": "The HTTP request method to be used for the webhook call.",
"WEBHOOK_REQUEST_METHOD_name": "Request method",
"WEBHOOK_SECRET_description": "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more informations <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_SECRET.md\">here</a>.",
"WEBHOOK_SECRET_description": "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more informations <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_SECRET.md\">here</a>.",
"WEBHOOK_SECRET_name": "HMAC Secret",
"WEBHOOK_SIZE_description": "The maximum size of the webhook payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
"WEBHOOK_SIZE_name": "Max payload size",
@@ -700,7 +723,7 @@
"settings_enabled": "",
"settings_enabled_icon": "",
"settings_expand_all": "Expand all",
"settings_imported": "Last time settings were imported from the pialert.conf file:",
"settings_imported": "Last time settings were imported from the app.conf file:",
"settings_imported_label": "",
"settings_missing": "Not all settings loaded, refresh the page! This is probably caused by a high load on the database or app startup sequence.",
"settings_missing_block": "You can not save your settings without specifying all setting keys. Refresh the page. This is probably caused by a high load on the database.",
@@ -711,9 +734,9 @@
"settings_publishers": "",
"settings_publishers_icon": "",
"settings_publishers_label": "",
"settings_saved": "<br/>Settings saved to the <code>pialert.conf</code> file.<br/><br/>A time-stamped backup of the previous file created. <br/><br/> Reloading...<br/>",
"settings_saved": "<br/>Settings saved to the <code>app.conf</code> file.<br/><br/>A time-stamped backup of the previous file created. <br/><br/> Reloading...<br/>",
"settings_system_icon": "",
"settings_system_label": "",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Save your changes at first before you test your settings."
}
}

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