Compare commits
249 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c570ff1d1c | ||
|
|
c462a83c3d | ||
|
|
81a2f34731 | ||
|
|
af9ce3bb55 | ||
|
|
f2593a113b | ||
|
|
4e376aad73 | ||
|
|
dbf0e3f777 | ||
|
|
a21ac1fab3 | ||
|
|
796413429b | ||
|
|
27b4349ec8 | ||
|
|
a1b025d461 | ||
|
|
9f1247141e | ||
|
|
72cec47e11 | ||
|
|
b55bab964e | ||
|
|
da171f6d3c | ||
|
|
8e7e437b4c | ||
|
|
d75f27c6db | ||
|
|
1779da3be0 | ||
|
|
17ab77e78f | ||
|
|
ed983279d5 | ||
|
|
e7ce7513ae | ||
|
|
ae0ba6ed8f | ||
|
|
6700565c8b | ||
|
|
efeb15de76 | ||
|
|
30c7035f30 | ||
|
|
7fb4db01e7 | ||
|
|
98080fba9f | ||
|
|
db3539615f | ||
|
|
77bff384b8 | ||
|
|
a7abd31f77 | ||
|
|
bc7e3519e1 | ||
|
|
d10c60f569 | ||
|
|
7b714064bb | ||
|
|
b977781937 | ||
|
|
ee90897208 | ||
|
|
121178452f | ||
|
|
421d5129ff | ||
|
|
8579b010c6 | ||
|
|
0d20562930 | ||
|
|
63b3c4eadb | ||
|
|
b2185f48a7 | ||
|
|
5b1eecfd7d | ||
|
|
ccce4f9edf | ||
|
|
5cb7553ed5 | ||
|
|
b003df323d | ||
|
|
eb473cac21 | ||
|
|
6213fe84de | ||
|
|
3e26cf67bb | ||
|
|
81fef80432 | ||
|
|
67c18c16d0 | ||
|
|
5ca85137ac | ||
|
|
f32ebb2557 | ||
|
|
052ce7362a | ||
|
|
6c0de70c76 | ||
|
|
cacc52cd27 | ||
|
|
db765fe78d | ||
|
|
8c023e4cb5 | ||
|
|
e9cc57a2fc | ||
|
|
4f04562b67 | ||
|
|
775a119f32 | ||
|
|
f06e084336 | ||
|
|
4329ff98ac | ||
|
|
4eae7e1023 | ||
|
|
1bc2fe6cd2 | ||
|
|
e0313f5970 | ||
|
|
cdca7488fb | ||
|
|
f4068165d0 | ||
|
|
7653ddce63 | ||
|
|
77eb472416 | ||
|
|
1369017216 | ||
|
|
ad294cd612 | ||
|
|
3e0b980548 | ||
|
|
116806b68b | ||
|
|
8155af8813 | ||
|
|
1720df4036 | ||
|
|
13f5e68eba | ||
|
|
7147f0691d | ||
|
|
70fcd90f8b | ||
|
|
aec0002837 | ||
|
|
980e83e039 | ||
|
|
1f735e9ed5 | ||
|
|
f56d7c686d | ||
|
|
e51f2d06d0 | ||
|
|
cbc9351961 | ||
|
|
1367649554 | ||
|
|
b4143607a1 | ||
|
|
69450c5885 | ||
|
|
cc19a6e3c0 | ||
|
|
af8c053ded | ||
|
|
a672070ff0 | ||
|
|
f85466e1d6 | ||
|
|
bb14627bbe | ||
|
|
8ebe696a8d | ||
|
|
2c5d95ba6d | ||
|
|
ee6430e34e | ||
|
|
f44ec2ce51 | ||
|
|
962f355d1c | ||
|
|
f5b62a20dd | ||
|
|
f09ac5bc86 | ||
|
|
2beef711a4 | ||
|
|
990ace45d1 | ||
|
|
28e0bc8403 | ||
|
|
d7af5d6611 | ||
|
|
634e6a7499 | ||
|
|
046022e2ea | ||
|
|
8d63c6b1ad | ||
|
|
1d3eb50c01 | ||
|
|
6588fc52cb | ||
|
|
7f3938715c | ||
|
|
fc554dcbcb | ||
|
|
cb324890c8 | ||
|
|
2336befcc1 | ||
|
|
bb2accc194 | ||
|
|
67f3c6dea7 | ||
|
|
f9a999c4d0 | ||
|
|
8d4d985fba | ||
|
|
63fc716359 | ||
|
|
ff73b3e2c7 | ||
|
|
e7b70cc104 | ||
|
|
7c084f31d1 | ||
|
|
9b1cf13924 | ||
|
|
bb83b4b8bd | ||
|
|
7d18dd546e | ||
|
|
5584512bcc | ||
|
|
de5e120042 | ||
|
|
d72812d280 | ||
|
|
ea3871c69b | ||
|
|
220b14e261 | ||
|
|
27a3b9f6c9 | ||
|
|
b4001f54bb | ||
|
|
47d1740fdd | ||
|
|
03d1e0e097 | ||
|
|
08ee4adddd | ||
|
|
1a221fabc9 | ||
|
|
f412ca0636 | ||
|
|
6beb2584e5 | ||
|
|
8419750bdd | ||
|
|
9364cea706 | ||
|
|
6ceff80ec5 | ||
|
|
cc9e4c722a | ||
|
|
5e687e1bdb | ||
|
|
d955e058e1 | ||
|
|
0615611a49 | ||
|
|
59243813a8 | ||
|
|
195206c699 | ||
|
|
2f170fb156 | ||
|
|
e7764324dc | ||
|
|
958444984a | ||
|
|
594af4903e | ||
|
|
dd4de7c5a3 | ||
|
|
1fa49a7730 | ||
|
|
7c70d435e4 | ||
|
|
2e159635c6 | ||
|
|
23aa1e4e85 | ||
|
|
a99dbaef78 | ||
|
|
06a1fa3512 | ||
|
|
e2270b4439 | ||
|
|
4c790c6ff2 | ||
|
|
07432daa28 | ||
|
|
54901be437 | ||
|
|
fb1e73d7d2 | ||
|
|
1401a24533 | ||
|
|
27ae11c1bc | ||
|
|
8817f8d0e9 | ||
|
|
4f9e8c5ecd | ||
|
|
c201e98f5b | ||
|
|
7cd76178b1 | ||
|
|
bcf4144364 | ||
|
|
78352f77b7 | ||
|
|
e38d2f9055 | ||
|
|
a66df76f74 | ||
|
|
a6d3c92d2a | ||
|
|
9720a15e91 | ||
|
|
6a0033da75 | ||
|
|
6fcdaf8843 | ||
|
|
97fc553278 | ||
|
|
bb57080b06 | ||
|
|
1310a4b751 | ||
|
|
1c7e729036 | ||
|
|
d7af580488 | ||
|
|
37e163e883 | ||
|
|
785f7c03bf | ||
|
|
849c39d75d | ||
|
|
c57e3e7557 | ||
|
|
ddc747e192 | ||
|
|
92801d6ddc | ||
|
|
b6c464be6d | ||
|
|
be81668d6d | ||
|
|
8e85abfda4 | ||
|
|
5559194617 | ||
|
|
1cc5cd56f8 | ||
|
|
9d4759898d | ||
|
|
178ff30938 | ||
|
|
a44575926f | ||
|
|
6a367c826e | ||
|
|
83336d3289 | ||
|
|
12ba6fbdad | ||
|
|
17a4656c41 | ||
|
|
7ef3fe5ac0 | ||
|
|
06c7ffa39e | ||
|
|
9ac0163f20 | ||
|
|
0126e448cc | ||
|
|
2362622cd0 | ||
|
|
ca2df744df | ||
|
|
9420c41e7c | ||
|
|
a015466c7f | ||
|
|
89f2c28046 | ||
|
|
57d0680b6a | ||
|
|
ddd405f379 | ||
|
|
3c38909b57 | ||
|
|
e830d1718e | ||
|
|
0ab78ffab7 | ||
|
|
9685784452 | ||
|
|
2a9085151f | ||
|
|
c6fb35838a | ||
|
|
588ddf3cb3 | ||
|
|
84f96d72c8 | ||
|
|
ed2ba9a435 | ||
|
|
265d313719 | ||
|
|
21ebc55335 | ||
|
|
a7bfc6f6f6 | ||
|
|
369fc44183 | ||
|
|
6a2a56e059 | ||
|
|
b0008ebd3f | ||
|
|
c624bfeae0 | ||
|
|
624d7499a5 | ||
|
|
4f5fbb1316 | ||
|
|
7d715493a6 | ||
|
|
0c92bf8d0a | ||
|
|
ea51b93263 | ||
|
|
539556e01d | ||
|
|
43e9fc324f | ||
|
|
e6e4620e13 | ||
|
|
6963e0b507 | ||
|
|
460f8038f2 | ||
|
|
ee2e228e15 | ||
|
|
15ab54f5d5 | ||
|
|
2226b9ff39 | ||
|
|
d4b701653e | ||
|
|
34f5658516 | ||
|
|
ea7dfa832d | ||
|
|
9bbd549d93 | ||
|
|
7424cf4645 | ||
|
|
19f767a887 | ||
|
|
57d9024ed3 | ||
|
|
87dd1cdf2d | ||
|
|
fdf381d565 | ||
|
|
20e29ecd15 | ||
|
|
a6ce702487 |
@@ -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
@@ -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
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -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
|
||||
|
||||
12
.github/ISSUE_TEMPLATE/i-have-an-issue.yml
vendored
@@ -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
|
||||
|
||||
6
.github/workflows/docker_cache-cleaner.yml
vendored
@@ -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
|
||||
7
.github/workflows/docker_dev.yml
vendored
@@ -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
|
||||
|
||||
7
.github/workflows/docker_prod.yml
vendored
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
76
Dockerfile
@@ -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
@@ -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"]
|
||||
|
||||
|
||||
80
README.md
@@ -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).
|
||||
|
||||
[](https://github.com/jokob-sk/Pi.Alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||

|
||||
[](https://github.com/jokob-sk/NetAlertX)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||
[](https://github.com/jokob-sk/NetAlertX/releases)
|
||||
[](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 😄
|
||||
[](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 -->
|
||||
|
||||
| [](https://github.com/sponsors/jokob-sk) | [](https://www.buymeacoffee.com/jokobsk) | [](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...
|
||||
|
||||
[](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"
|
||||
|
||||
@@ -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 #
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)">©</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>
|
||||
@@ -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)">©</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>
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
[](https://github.com/jokob-sk/Pi.Alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||

|
||||
[](https://github.com/jokob-sk/NetAlertX)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||
[](https://hub.docker.com/r/jokobsk/netalertx)
|
||||

|
||||
[](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
|
||||
|
||||
| [](https://github.com/sponsors/jokob-sk) | [](https://www.buymeacoffee.com/jokobsk) | [](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.
|
||||
@@ -1,232 +0,0 @@
|
||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
|
||||
[](https://github.com/jokob-sk/Pi.Alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/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
@@ -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
@@ -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}
|
||||
"
|
||||
10
docs/API.md
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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] |
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
|
||||
# 📝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.
|
||||
|
||||

|
||||
|
||||
> [!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)
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -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***
|
||||
|
||||
@@ -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.
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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).
|
||||
|
||||

|
||||
|
||||
## ⚙ 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.
|
||||
|
||||

|
||||
## Adding new icons
|
||||
|
||||

|
||||
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`.
|
||||

|
||||
|
||||
- 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.
|
||||

|
||||
|
||||
2. Navigate to the device you want to use the icon on and click the "+" icon:
|
||||
|
||||

|
||||
|
||||
3. Paste in the copied HTML or SVG code and click "OK":
|
||||
|
||||

|
||||
|
||||
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
@@ -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
|
||||
```
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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***
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -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"
|
||||
12
docs/SMTP.md
@@ -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'
|
||||
```
|
||||
|
||||
|
||||
@@ -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.
|
||||
> 
|
||||
|
||||
* 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`).
|
||||

|
||||
|
||||
> [!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.
|
||||
|
||||
|
||||
@@ -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).
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
### 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
|
||||

|
||||
|
||||
```
|
||||
@@ -14,5 +16,5 @@ New devices count: {{ $json["body"]["attachments"][0]["text"]["new_devices"].len
|
||||
### Get your webhook in n8n
|
||||

|
||||
|
||||
### Configure PiAlert to point to the above URL
|
||||

|
||||
### Configure NetAlertX to point to the above URL
|
||||

|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`
|
||||
|
||||
BIN
docs/img/DEVICES_BULK_EDITING/MULTI-EDIT.gif
Executable file
|
After Width: | Height: | Size: 443 KiB |
BIN
docs/img/HOME_ASISSTANT/HomeAssistant-Configuration.png
Executable file
|
After Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
BIN
docs/img/ICONS/device_add_icon.png
Executable file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/img/ICONS/font_awesome_copy_html.png
Executable file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/img/ICONS/iconify_design_copy_svg.png
Executable file
|
After Width: | Height: | Size: 67 KiB |
BIN
docs/img/ICONS/paste-svg.png
Executable file
|
After Width: | Height: | Size: 58 KiB |
BIN
docs/img/SUBNETS/system_info-network_hardware.png
Executable file
|
After Width: | Height: | Size: 102 KiB |
@@ -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
|
||||
----------------------------------------------------------------------------- */
|
||||
@@ -725,4 +725,6 @@ input[type="password"]::-webkit-caps-lock-indicator {
|
||||
}
|
||||
.pa_semitransparent-panel{
|
||||
background-color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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>     </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¶meter='+ 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¶meter='+ 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¶meter='+ 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¶meter='+ 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
After Width: | Height: | Size: 6.0 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Pi-Alert Console",
|
||||
"short_name": "Pi-Alert",
|
||||
"name": "NetAlertX Console",
|
||||
"short_name": "NetAlertX",
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 41 KiB |
@@ -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
18
front/js/db_methods.js
Executable 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);
|
||||
});
|
||||
}
|
||||
@@ -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: {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
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¶meter=' + parameter +
|
||||
'&value='+ value,
|
||||
function(data) {
|
||||
if (data != "OK") {
|
||||
// Retry
|
||||
sleep (200);
|
||||
$.get('php/server/parameters.php?action=set¶meter=' + 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'), " ");
|
||||
text2 = text2.replace(new RegExp('<', 'g'), "<");
|
||||
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")
|
||||
|
||||
|
||||
@@ -163,4 +163,9 @@
|
||||
}
|
||||
|
||||
return true; // Return true if no schedules are found
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
286
front/js/ui_components.js
Executable 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")
|
||||
1
front/lib/AdminLTE/bower_components/datatables.net/css/select.dataTables.min.css
vendored
Executable 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}}
|
||||
38
front/lib/AdminLTE/bower_components/datatables.net/js/dataTables.select.min.js
vendored
Executable 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});
|
||||
@@ -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
@@ -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>
|
||||
<!-- ----------------------------------------------------------------------- -->
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
//------------------------------------------------------------------------------
|
||||
// Pi.Alert
|
||||
// NetAlertX
|
||||
// Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
//
|
||||
// events.php - Front module. Server side. Manage Events
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
###################################################################################
|
||||
# Pi.Alert #
|
||||
# NetAlertX #
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector #
|
||||
# #
|
||||
# internetinfo.php # Front module. Server side. System Information #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
###################################################################################
|
||||
# Pi.Alert #
|
||||
# NetAlertX #
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector #
|
||||
# #
|
||||
# nslookup.php # Front module. Server side. System Information #
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
//------------------------------------------------------------------------------
|
||||
// Pi.Alert
|
||||
// NetAlertX
|
||||
// Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
//
|
||||
// parameters.php - Front module. Server side. Manage Parameters
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
###################################################################################
|
||||
# Pi.Alert #
|
||||
# NetAlertX #
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector #
|
||||
# #
|
||||
# traceroute.php # Front module. Server side. System Information #
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
<!-- © 2022 jokob-sk -->
|
||||
<span style="display:inline-block; transform: rotate(180deg)">©</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">©</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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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­tümer",
|
||||
"DevDetail_MainInfo_Owner": "Eigen­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 > 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 > 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 Funktion 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­ungen befinden sich im Datenbank-Ver­zeich­nis, gepackt als zip-Archive, benannt mit dem Erstellungs­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht rück­gängig gemacht werden. Alle Geräte werden in der Datenbank ge­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 Funktion nutzen. Der Vorgang kann ohne Backup nicht rückgängig gemacht werden. Alle Ereignisse älter als 30 Tage werden aus der Datenbank gelöscht. Dies setzt auch die Anwesenheit zurü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­tion nutzen. Der Vor­gang kann ohne Back­up nicht rück­gängig gemacht werden. Alle Ereignisse werden aus der Datenbank ge­löscht. Dies setzt auch die Anwesenheit zu­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht rück­gängig gemacht werden. Alle Geäte ohne MAC-Adresse werden aus der Datenbank ge­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht rück­gängig gemacht werden. Alle Gräte mit dem Namen (unknown) werden aus der Datenbank ge­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht r\u00fcck­g\u00e4ngig gemacht werden. Alle Ger\u00e4te werden in der Datenbank ge­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht r\u00fcck­g\u00e4ngig gemacht werden. Alle Ereignisse werden aus der Datenbank ge­l\u00f6scht. Dies setzt auch die Anwesenheit zu­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht r\u00fcck­g\u00e4ngig gemacht werden. Alle Ge\u00e4te ohne MAC-Adresse werden aus der Datenbank ge­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­tion nutzen. Der Vor­gang kann ohne Back­up nicht r\u00fcck­g\u00e4ngig gemacht werden. Alle Gr\u00e4te mit dem Namen (unknown) werden aus der Datenbank ge­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­tion wiederhergestellt werden. Ältere Sicher­ungen müssen manuell wieder­hergestellt wer­den. Es empfiehlt sich eine Integritäts­prüfung nach der Wieder­her­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­tion wiederhergestellt werden. \u00c4ltere Sicher­ungen m\u00fcssen manuell wieder­hergestellt wer­den. Es empfiehlt sich eine Integrit\u00e4ts­pr\u00fcfung nach der Wieder­her­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­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."
|
||||
}
|
||||
}
|
||||