mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Compare commits
150 Commits
39d7642484
...
v24.9.26
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15a7779d6e | ||
|
|
2784f2ebeb | ||
|
|
d46046beea | ||
|
|
6233f4d646 | ||
|
|
31411e0a14 | ||
|
|
8d824af3bd | ||
|
|
f05f0d625a | ||
|
|
2fec3b6607 | ||
|
|
f285a28887 | ||
|
|
11cb47fada | ||
|
|
d8b413b5e7 | ||
|
|
656bba7ff7 | ||
|
|
a2cf8c1167 | ||
|
|
737cb07403 | ||
|
|
3febbc21cb | ||
|
|
7e14fae29c | ||
|
|
a16fe4561b | ||
|
|
f2afe9d681 | ||
|
|
f8c0a5a1ef | ||
|
|
631e992411 | ||
|
|
feafaff218 | ||
|
|
f6a06842cc | ||
|
|
0cc3ede86c | ||
|
|
aa277136c6 | ||
|
|
82ccb0c0b6 | ||
|
|
30750a9449 | ||
|
|
5278af48c5 | ||
|
|
77f19c3575 | ||
|
|
10df7363d6 | ||
|
|
06e49f7adb | ||
|
|
9fcbd9d64e | ||
|
|
c6888a79fd | ||
|
|
ef458903b7 | ||
|
|
b544734209 | ||
|
|
815810dc7a | ||
|
|
552d79eee8 | ||
|
|
2f70e2e8d8 | ||
|
|
4a20b66c92 | ||
|
|
36cec0ab38 | ||
|
|
6bde0f9084 | ||
|
|
f64ef5b881 | ||
|
|
1895f68233 | ||
|
|
d2fe53bc81 | ||
|
|
e9e45c34ae | ||
|
|
064a51acee | ||
|
|
7340ce6da2 | ||
|
|
703885308a | ||
|
|
71856b49a4 | ||
|
|
86c7d26107 | ||
|
|
d858f4f9d0 | ||
|
|
aefe470d31 | ||
|
|
99fb60c1b5 | ||
|
|
ec37e4d71b | ||
|
|
e240821d6c | ||
|
|
632e441dda | ||
|
|
24f7935891 | ||
|
|
dcc43d1f3c | ||
|
|
8f35bf36ff | ||
|
|
1548168eba | ||
|
|
2e35bac6ec | ||
|
|
ba348fc4c2 | ||
|
|
d3337e75a9 | ||
|
|
9e0bc043b0 | ||
|
|
29fdd0b115 | ||
|
|
48e92a186e | ||
|
|
1dcb66e972 | ||
|
|
fa0d6d312d | ||
|
|
a19fe342e7 | ||
|
|
c4fc68cac8 | ||
|
|
3a050c31a7 | ||
|
|
2cd406a390 | ||
|
|
b086417686 | ||
|
|
dbecbfc85f | ||
|
|
3f9e4c4425 | ||
|
|
4fd1869bde | ||
|
|
78025a376c | ||
|
|
615fd08f5b | ||
|
|
4839211fe1 | ||
|
|
19aaa92fa3 | ||
|
|
43aa40efbb | ||
|
|
95f48cb70d | ||
|
|
8c0da1d0df | ||
|
|
b0d07a6adc | ||
|
|
ee23ae19f7 | ||
|
|
0c73e49245 | ||
|
|
899a0c3608 | ||
|
|
d188b640e4 | ||
|
|
a95eb45924 | ||
|
|
f737a71939 | ||
|
|
9df97e0e33 | ||
|
|
4ce7077599 | ||
|
|
605a33330b | ||
|
|
9bd5ff10b4 | ||
|
|
45d3be2439 | ||
|
|
46209e3e47 | ||
|
|
9b9836cae2 | ||
|
|
89be97bfb2 | ||
|
|
3e4f64a7c6 | ||
|
|
50fbd6e616 | ||
|
|
5a96ad2304 | ||
|
|
25667014fc | ||
|
|
955472ef5c | ||
|
|
e32b60cafc | ||
|
|
3033c617fa | ||
|
|
1688836b4f | ||
|
|
f30b6b7fc1 | ||
|
|
0c5c754f38 | ||
|
|
da21ee6477 | ||
|
|
3a268add06 | ||
|
|
03b610a6ec | ||
|
|
38f70fd045 | ||
|
|
3473fabdbf | ||
|
|
46186e5d3b | ||
|
|
e0dd3ab53e | ||
|
|
c385ac68f4 | ||
|
|
e1c446b0df | ||
|
|
0413ac5fb4 | ||
|
|
01f8dc5f6b | ||
|
|
00451a6846 | ||
|
|
b181e2ada6 | ||
|
|
73a0a49934 | ||
|
|
b3ad58f5f3 | ||
|
|
03e0061b03 | ||
|
|
e5a63e9caa | ||
|
|
eb3a54ff1c | ||
|
|
b3b8196b64 | ||
|
|
408d8cb7c5 | ||
|
|
57d94634f1 | ||
|
|
3778dcb3ad | ||
|
|
393a0d8168 | ||
|
|
c98c22c27d | ||
|
|
54ae8a7b35 | ||
|
|
a2cc2b441e | ||
|
|
a3c0974e77 | ||
|
|
b7fa32f70a | ||
|
|
7fd8b039ed | ||
|
|
303cadc68c | ||
|
|
61ab586bd6 | ||
|
|
0c64bd392b | ||
|
|
fa0e07a511 | ||
|
|
d699f6744e | ||
|
|
84f0221615 | ||
|
|
2e34b1ff41 | ||
|
|
8238eccb75 | ||
|
|
a6f86ee44a | ||
|
|
c9e92469a4 | ||
|
|
87fb4a105a | ||
|
|
6f2cf76bda | ||
|
|
09531dc207 | ||
|
|
ae1673c1c3 |
28
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
28
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -9,20 +9,6 @@ body:
|
||||
options:
|
||||
- label: I have searched the existing open and closed issues
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Am I willing to test this? 🧪
|
||||
description: I rely on the community to test unreleased features. If you are requesting a feature, please be willing to test it within 48h of test request. Otherwise, the feature might be pulled from the code base.
|
||||
options:
|
||||
- label: I will do my best to test this feature on the `netlertx-dev` image when requested within 48h and report bugs to help deliver a great user experience for everyone and not to break existing installations.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Can I help implement this? 👩💻👨💻
|
||||
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs
|
||||
options:
|
||||
- label: "Yes"
|
||||
- label: "No"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe
|
||||
@@ -50,3 +36,17 @@ body:
|
||||
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Am I willing to test this? 🧪
|
||||
description: I rely on the community to test unreleased features. If you are requesting a feature, please be willing to test it within 48h of test request. Otherwise, the feature might be pulled from the code base.
|
||||
options:
|
||||
- label: I will do my best to test this feature on the `netlertx-dev` image when requested within 48h and report bugs to help deliver a great user experience for everyone and not to break existing installations.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Can I help implement this? 👩💻👨💻
|
||||
description: The maintainer will provide guidance and help. The implementer will read the PR guidelines https://github.com/jokob-sk/NetAlertX/tree/main/docs#-pull-requests-prs
|
||||
options:
|
||||
- label: "Yes"
|
||||
- label: "No"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM alpine:3.20 as builder
|
||||
FROM alpine:3.20 AS builder
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache bash python3 python3-dev gcc musl-dev libffi-dev openssl-dev \
|
||||
@@ -21,7 +21,7 @@ RUN pip install netifaces tplink-omada-client pycryptodome requests paho-mqtt sc
|
||||
&& bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"
|
||||
|
||||
# second stage
|
||||
FROM alpine:3.20 as runner
|
||||
FROM alpine:3.20 AS runner
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
# default UID and GID
|
||||
ENV USER=pi USER_ID=1000 USER_GID=1000 PORT=20211
|
||||
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
|
||||
|
||||
11
README.md
11
README.md
@@ -1,12 +1,13 @@
|
||||
[](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://discord.gg/UQnnHNYV)
|
||||
|
||||
# 🖧🔍 Network scanner & notification framework
|
||||
|
||||
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/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/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) |
|
||||
|----------------------|----------------------| ----------------------| ----------------------|
|
||||
|
||||
@@ -64,7 +64,9 @@ services:
|
||||
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
|
||||
# ---------------------------------------------------------------------------
|
||||
environment:
|
||||
# - APP_CONF_OVERRIDE={"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","UI_dark_mode":"True"}
|
||||
- TZ=${TZ}
|
||||
- PORT=${PORT}
|
||||
- PORT=${PORT}
|
||||
# ❗ DANGER ZONE BELOW - Setting ALWAYS_FRESH_INSTALL=true will delete the content of the /db & /config folders
|
||||
- ALWAYS_FRESH_INSTALL=${ALWAYS_FRESH_INSTALL}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[](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)
|
||||
[](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://discord.gg/UQnnHNYV)
|
||||
|
||||
|
||||
# NetAlertX 🖧🔍 Network scanner & notification framework
|
||||
|
||||
@@ -40,7 +41,8 @@ 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` |
|
||||
|`ALWAYS_FRESH_INSTALL` | Setting to `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` |
|
||||
|`APP_CONF_OVERRIDE` | JSON override for settings, e.g. `{"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","UI_dark_mode":"True"}` (Experimental 🧪) | `N/A` |
|
||||
|`ALWAYS_FRESH_INSTALL` | If `true` will delete the content of the `/db` & `/config` folders. For testing purposes. Can be coupled with [watchtower](https://github.com/containrrr/watchtower) to have an always freshly installed `netalertx`/`netalertx-dev` image. | `N/A` |
|
||||
|
||||
### Docker paths
|
||||
|
||||
@@ -89,9 +91,10 @@ Use the official installation guides at first and use community content as suppl
|
||||
- 📄 [How to Install NetAlertX on Your Synology NAS - Marius hosting](https://mariushosting.com/how-to-install-pi-alert-on-your-synology-nas/) (Updated frequently)
|
||||
- 📄 [Using the PiAlert Network Security Scanner on a Raspberry Pi - PiMyLifeUp](https://pimylifeup.com/raspberry-pi-pialert/)
|
||||
- ▶ [How to Setup Pi.Alert on Your Synology NAS - Digital Aloha](https://www.youtube.com/watch?v=M4YhpuRFaUg)
|
||||
- 📄 [시놀/헤놀에서 네트워크 스캐너 Pi.Alert Docker로 설치 및 사용하기 (Korean)](https://blog.dalso.org/article/%EC%8B%9C%EB%86%80-%ED%97%A4%EB%86%80%EC%97%90%EC%84%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%8A%A4%EC%BA%90%EB%84%88-pi-alert-docker%EB%A1%9C-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9) (July 2023)
|
||||
- 📄 [防蹭网神器,网络安全助手 | 极空间部署网络扫描和通知系统『NetAlertX』](https://blog.csdn.net/qq_63499861/article/details/141105273)
|
||||
- 📄 [시놀/헤놀에서 네트워크 스캐너 Pi.Alert Docker로 설치 및 사용하기](https://blog.dalso.org/article/%EC%8B%9C%EB%86%80-%ED%97%A4%EB%86%80%EC%97%90%EC%84%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%8A%A4%EC%BA%90%EB%84%88-pi-alert-docker%EB%A1%9C-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9) (July 2023)
|
||||
- 📄 [网络入侵探测器Pi.Alert (Chinese)](https://codeantenna.com/a/VgUvIAjZ7J) (May 2023)
|
||||
- ▶ [Pi.Alert auf Synology & Docker by - Jürgen Barth (German)](https://www.youtube.com/watch?v=-ouvA2UNu-A) (March 2023)
|
||||
- ▶ [Pi.Alert auf Synology & Docker by - Jürgen Barth](https://www.youtube.com/watch?v=-ouvA2UNu-A) (March 2023)
|
||||
- ▶ [Top Docker Container for Home Server Security - VirtualizationHowto](https://www.youtube.com/watch?v=tY-w-enLF6Q) (March 2023)
|
||||
- ▶ [Pi.Alert or WatchYourLAN can alert you to unknown devices appearing on your WiFi or LAN network - Danie van der Merwe](https://www.youtube.com/watch?v=v6an9QG2xF0) (November 2022)
|
||||
|
||||
|
||||
@@ -41,6 +41,16 @@ if [ "$ALWAYS_FRESH_INSTALL" = true ]; then
|
||||
rm -rf "$INSTALL_DIR_OLD/db/"*
|
||||
fi
|
||||
|
||||
# OVERRIDE settings: Handling APP_CONF_OVERRIDE
|
||||
# Check if APP_CONF_OVERRIDE is set
|
||||
if [ -z "$APP_CONF_OVERRIDE" ]; then
|
||||
echo "APP_CONF_OVERRIDE is not set. Skipping config file creation."
|
||||
else
|
||||
# Save the APP_CONF_OVERRIDE env variable as a JSON file
|
||||
echo "$APP_CONF_OVERRIDE" > "${INSTALL_DIR}/config/app_conf_override.json"
|
||||
echo "Config file saved to ${INSTALL_DIR}/config/app_conf_override.json"
|
||||
fi
|
||||
|
||||
# 🔻 FOR BACKWARD COMPATIBILITY - REMOVE AFTER 12/12/2024
|
||||
|
||||
# Check if pialert.db exists, then create a symbolic link to app.db
|
||||
|
||||
275
docs/AUTHELIA.md
Executable file
275
docs/AUTHELIA.md
Executable file
@@ -0,0 +1,275 @@
|
||||
(DRAFT) Authelia support
|
||||
|
||||
|
||||
|
||||
```yaml
|
||||
theme: dark
|
||||
|
||||
default_2fa_method: "totp"
|
||||
|
||||
server:
|
||||
address: 0.0.0.0:9091
|
||||
endpoints:
|
||||
enable_expvars: false
|
||||
enable_pprof: false
|
||||
authz:
|
||||
forward-auth:
|
||||
implementation: 'ForwardAuth'
|
||||
authn_strategies:
|
||||
- name: 'HeaderAuthorization'
|
||||
schemes:
|
||||
- 'Basic'
|
||||
- name: 'CookieSession'
|
||||
ext-authz:
|
||||
implementation: 'ExtAuthz'
|
||||
authn_strategies:
|
||||
- name: 'HeaderAuthorization'
|
||||
schemes:
|
||||
- 'Basic'
|
||||
- name: 'CookieSession'
|
||||
auth-request:
|
||||
implementation: 'AuthRequest'
|
||||
authn_strategies:
|
||||
- name: 'HeaderAuthRequestProxyAuthorization'
|
||||
schemes:
|
||||
- 'Basic'
|
||||
- name: 'CookieSession'
|
||||
legacy:
|
||||
implementation: 'Legacy'
|
||||
authn_strategies:
|
||||
- name: 'HeaderLegacy'
|
||||
- name: 'CookieSession'
|
||||
disable_healthcheck: false
|
||||
tls:
|
||||
key: ""
|
||||
certificate: ""
|
||||
client_certificates: []
|
||||
headers:
|
||||
csp_template: ""
|
||||
|
||||
log:
|
||||
## Level of verbosity for logs: info, debug, trace.
|
||||
level: info
|
||||
|
||||
###############################################################
|
||||
# The most important section
|
||||
###############################################################
|
||||
access_control:
|
||||
## Default policy can either be 'bypass', 'one_factor', 'two_factor' or 'deny'.
|
||||
default_policy: deny
|
||||
networks:
|
||||
- name: internal
|
||||
networks:
|
||||
- '192.168.0.0/18'
|
||||
- '10.10.10.0/8' # Zerotier
|
||||
- name: private
|
||||
networks:
|
||||
- '172.16.0.0/12'
|
||||
rules:
|
||||
- networks:
|
||||
- private
|
||||
domain:
|
||||
- '*'
|
||||
policy: bypass
|
||||
- networks:
|
||||
- internal
|
||||
domain:
|
||||
- '*'
|
||||
policy: bypass
|
||||
- domain:
|
||||
# exclude itself from auth, should not happen as we use Traefik middleware on a case-by-case screnario
|
||||
- 'auth.MYDOMAIN1.TLD'
|
||||
- 'authelia.MYDOMAIN1.TLD'
|
||||
- 'auth.MYDOMAIN2.TLD'
|
||||
- 'authelia.MYDOMAIN2.TLD'
|
||||
policy: bypass
|
||||
- domain:
|
||||
#All subdomains match
|
||||
- 'MYDOMAIN1.TLD'
|
||||
- '*.MYDOMAIN1.TLD'
|
||||
policy: two_factor
|
||||
- domain:
|
||||
# This will not work yet as Authelio does not support multi-domain authentication
|
||||
- 'MYDOMAIN2.TLD'
|
||||
- '*.MYDOMAIN2.TLD'
|
||||
policy: two_factor
|
||||
|
||||
|
||||
############################################################
|
||||
identity_validation:
|
||||
reset_password:
|
||||
jwt_secret: "[REDACTED]"
|
||||
|
||||
identity_providers:
|
||||
oidc:
|
||||
enable_client_debug_messages: true
|
||||
enforce_pkce: public_clients_only
|
||||
hmac_secret: [REDACTED]
|
||||
lifespans:
|
||||
authorize_code: 1m
|
||||
id_token: 1h
|
||||
refresh_token: 90m
|
||||
access_token: 1h
|
||||
cors:
|
||||
endpoints:
|
||||
- authorization
|
||||
- token
|
||||
- revocation
|
||||
- introspection
|
||||
- userinfo
|
||||
allowed_origins:
|
||||
- "*"
|
||||
allowed_origins_from_client_redirect_uris: false
|
||||
jwks:
|
||||
- key: [REDACTED]
|
||||
certificate_chain:
|
||||
clients:
|
||||
- client_id: portainer
|
||||
client_name: Portainer
|
||||
# generate secret with "authelia crypto hash generate pbkdf2 --random --random.length 32 --random.charset alphanumeric"
|
||||
# Random Password: [REDACTED]
|
||||
# Digest: [REDACTED]
|
||||
client_secret: [REDACTED]
|
||||
token_endpoint_auth_method: 'client_secret_post'
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
consent_mode: pre-configured #explicit
|
||||
pre_configured_consent_duration: '6M' #Must be re-authorised every 6 Months
|
||||
scopes:
|
||||
- openid
|
||||
#- groups #Currently not supported in Authelia V
|
||||
- email
|
||||
- profile
|
||||
redirect_uris:
|
||||
- https://portainer.MYDOMAIN1.LTD
|
||||
userinfo_signed_response_alg: none
|
||||
|
||||
- client_id: openproject
|
||||
client_name: OpenProject
|
||||
# generate secret with "authelia crypto hash generate pbkdf2 --random --random.length 32 --random.charset alphanumeric"
|
||||
# Random Password: [REDACTED]
|
||||
# Digest: [REDACTED]
|
||||
client_secret: [REDACTED]
|
||||
token_endpoint_auth_method: 'client_secret_basic'
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
consent_mode: pre-configured #explicit
|
||||
pre_configured_consent_duration: '6M' #Must be re-authorised every 6 Months
|
||||
scopes:
|
||||
- openid
|
||||
#- groups #Currently not supported in Authelia V
|
||||
- email
|
||||
- profile
|
||||
redirect_uris:
|
||||
- https://op.MYDOMAIN.TLD
|
||||
#grant_types:
|
||||
# - refresh_token
|
||||
# - authorization_code
|
||||
#response_types:
|
||||
# - code
|
||||
#response_modes:
|
||||
# - form_post
|
||||
# - query
|
||||
# - fragment
|
||||
userinfo_signed_response_alg: none
|
||||
##################################################################
|
||||
|
||||
|
||||
telemetry:
|
||||
metrics:
|
||||
enabled: false
|
||||
address: tcp://0.0.0.0:9959
|
||||
|
||||
totp:
|
||||
disable: false
|
||||
issuer: authelia.com
|
||||
algorithm: sha1
|
||||
digits: 6
|
||||
period: 30 ## The period in seconds a one-time password is valid for.
|
||||
skew: 1
|
||||
secret_size: 32
|
||||
|
||||
webauthn:
|
||||
disable: false
|
||||
timeout: 60s ## Adjust the interaction timeout for Webauthn dialogues.
|
||||
display_name: Authelia
|
||||
attestation_conveyance_preference: indirect
|
||||
user_verification: preferred
|
||||
|
||||
ntp:
|
||||
address: "pool.ntp.org"
|
||||
version: 4
|
||||
max_desync: 5s
|
||||
disable_startup_check: false
|
||||
disable_failure: false
|
||||
|
||||
authentication_backend:
|
||||
password_reset:
|
||||
disable: false
|
||||
custom_url: ""
|
||||
refresh_interval: 5m
|
||||
file:
|
||||
path: /config/users_database.yml
|
||||
watch: true
|
||||
password:
|
||||
algorithm: argon2
|
||||
argon2:
|
||||
variant: argon2id
|
||||
iterations: 3
|
||||
memory: 65536
|
||||
parallelism: 4
|
||||
key_length: 32
|
||||
salt_length: 16
|
||||
|
||||
password_policy:
|
||||
standard:
|
||||
enabled: false
|
||||
min_length: 8
|
||||
max_length: 0
|
||||
require_uppercase: true
|
||||
require_lowercase: true
|
||||
require_number: true
|
||||
require_special: true
|
||||
## zxcvbn is a well known and used password strength algorithm. It does not have tunable settings.
|
||||
zxcvbn:
|
||||
enabled: false
|
||||
min_score: 3
|
||||
|
||||
regulation:
|
||||
max_retries: 3
|
||||
find_time: 2m
|
||||
ban_time: 5m
|
||||
|
||||
session:
|
||||
name: authelia_session
|
||||
secret: [REDACTED]
|
||||
expiration: 60m
|
||||
inactivity: 15m
|
||||
cookies:
|
||||
- domain: 'MYDOMAIN1.LTD'
|
||||
authelia_url: 'https://auth.MYDOMAIN1.LTD'
|
||||
name: 'authelia_session'
|
||||
default_redirection_url: 'https://MYDOMAIN1.LTD'
|
||||
- domain: 'MYDOMAIN2.LTD'
|
||||
authelia_url: 'https://auth.MYDOMAIN2.LTD'
|
||||
name: 'authelia_session_other'
|
||||
default_redirection_url: 'https://MYDOMAIN2.LTD'
|
||||
|
||||
storage:
|
||||
encryption_key: [REDACTED]
|
||||
local:
|
||||
path: /config/db.sqlite3
|
||||
|
||||
notifier:
|
||||
disable_startup_check: true
|
||||
smtp:
|
||||
address: MYOTHERDOMAIN.LTD:465
|
||||
timeout: 5s
|
||||
username: "USER@DOMAIN"
|
||||
password: "[REDACTED]"
|
||||
sender: "Authelia <postmaster@MYOTHERDOMAIN.LTD>"
|
||||
identifier: NAME@MYOTHERDOMAIN.LTD
|
||||
subject: "[Authelia] {title}"
|
||||
startup_check_address: postmaster@MYOTHERDOMAIN.LTD
|
||||
|
||||
```
|
||||
@@ -8,10 +8,10 @@ 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/app.conf` | Configuration file | Can be overridden with the [`APP_CONF_OVERRIDE` env variable](https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles#docker-environment-variables). |
|
||||
| `/config/devices.csv` | CSV file containing device information | Doesn't contain historical data |
|
||||
|
||||
## Data and cackup storage
|
||||
## Data and backup storage
|
||||
|
||||
To decide on a backup strategy, check where the data is stored:
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
| Pholus_Scan | Scan results of the Pholus python network penetration script. | ![Screen8][screen8] |
|
||||
| Plugins_Events | For capturing events exposed by a plugin via the `last_result.log` file. If unique then saved into the `Plugins_Objects` table. Entries are deleted once processed and stored in the `Plugins_History` and/or `Plugins_Objects` tables. | ![Screen10][screen10] |
|
||||
| Plugins_History | History of all entries from the `Plugins_Events` table | ![Screen11][screen11] |
|
||||
| Plugins_Language_Strings | Language strings colelcted from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] |
|
||||
| Plugins_Language_Strings | Language strings collected 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 `app.conf` and plugins coming from `config.json` files. | ![Screen16][screen16] |
|
||||
|
||||
@@ -518,6 +518,60 @@ Required attributes are:
|
||||
| (optional) `"override_value"` | Used to determine a user-defined override for the setting. Useful for template-based plugins, where you can choose to leave the current value or override it with the value defined in the setting. (Work in progress) |
|
||||
| (optional) `"events"` | Used to trigger the plugin. Usually used on the `RUN` setting. Not fully tested in all scenarios. Will show a play button next to the setting. After clicking, an event is generated for the backend in the `Parameters` database table to process the front-end event on the next run. |
|
||||
|
||||
### UI Component Types Documentation
|
||||
|
||||
This section outlines the structure and types of UI components, primarily used to build HTML forms or interactive elements dynamically. Each UI component has a `"type"` which defines its structure, behavior, and rendering options.
|
||||
|
||||
#### UI Component JSON Structure
|
||||
The UI component is defined as a JSON object containing a list of `elements`. Each element specifies how it should behave, with properties like `elementType`, `elementOptions`, and any associated `transformers` to modify the data. The example below demonstrates how a component with two elements (`span` and `select`) is structured:
|
||||
|
||||
```json
|
||||
{
|
||||
"function": "dev_Icon",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "span",
|
||||
"elementOptions": [
|
||||
{ "cssClasses": "input-group-addon iconPreview" },
|
||||
{ "getStringKey": "Gen_SelectToPreview" },
|
||||
{ "customId": "NEWDEV_dev_Icon_preview" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{
|
||||
"onChange": "updateIconPreview(this)"
|
||||
},
|
||||
{ "customParams": "NEWDEV_dev_Icon,NEWDEV_dev_Icon_preview" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Rendering Logic
|
||||
|
||||
The code snippet provided demonstrates how the elements are iterated over to generate their corresponding HTML. Depending on the `elementType`, different HTML tags (like `<select>`, `<input>`, `<textarea>`, `<button>`, etc.) are created with the respective attributes such as `onChange`, `my-data-type`, and `class` based on the provided `elementOptions`. Events can also be attached to elements like buttons or select inputs.
|
||||
|
||||
### Key Element Types
|
||||
|
||||
- **`select`**: Renders a dropdown list. Additional options like `isMultiSelect` and event handlers (e.g., `onChange`) can be attached.
|
||||
- **`input`**: Handles various types of input fields, including checkboxes, text, and others, with customizable attributes like `readOnly`, `placeholder`, etc.
|
||||
- **`button`**: Generates clickable buttons with custom event handlers (`onClick`), icons, or labels.
|
||||
- **`textarea`**: Creates a multi-line input box for text input.
|
||||
- **`span`**: Used for inline text or content with customizable classes and data attributes.
|
||||
|
||||
Each element may also have associated events (e.g., running a scan or triggering a notification) defined under `Events`.
|
||||
|
||||
|
||||
##### Supported settings `function` values
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ There is also an in-app Help / FAQ section that should be answering frequently a
|
||||
|
||||
- [Version history (legacy)](/docs/VERSIONS_HISTORY.md)
|
||||
- [Reverse proxy (Nginx, Apache, SWAG)](/docs/REVERSE_PROXY.md)
|
||||
- [Setting up Authelia](/docs/AUTHELIA.md) (DRAFT)
|
||||
|
||||
#### 👩💻For Developers👨💻
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ You need to specify the network interface and the network mask. You can also con
|
||||
* One subnet: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0']`
|
||||
* Two subnets: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0','192.168.1.0/24 --interface=eth1 -vlan=107']`
|
||||
|
||||
If you get timeout messages, decrease the network mask (e.g.: from a `/16` to `/24`) or increase the `TIMEOUT` setting (e.g.: `ARPSCAN_RUN_TIMEOUT` to `300` (a timeout of 5min)) for the plugin and the interval between scans (e.g.: `ARPSCAN_RUN_SCHD` to `*/10 * * * *` (scans every 10 min)).
|
||||
|
||||
## Explanation
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ showSpinner()
|
||||
$(document).ready(function() {
|
||||
|
||||
// Load JSON data from the provided URL
|
||||
$.getJSON('/api/table_appevents.json', function(data) {
|
||||
$.getJSON('api/table_appevents.json', function(data) {
|
||||
// Process the JSON data and generate UI dynamically
|
||||
processData(data)
|
||||
|
||||
|
||||
@@ -745,6 +745,18 @@ height: 50px;
|
||||
.infobox_label {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
.deviceSelector
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.deviceSelector input
|
||||
{
|
||||
width: 100% !important;
|
||||
display: inline-grid;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
/* report */
|
||||
/* --------------------------------------------------------- */
|
||||
@@ -1079,11 +1091,67 @@ input[readonly] {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#settingsPage .select2-selection
|
||||
{
|
||||
width: initial;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#settingsPage .form-control
|
||||
{
|
||||
min-height: 42px;
|
||||
}
|
||||
|
||||
#settingsPage .select2-selection
|
||||
{
|
||||
background-color: rgb(96, 96, 96);
|
||||
}
|
||||
#settingsPage .select2-container
|
||||
{
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
#settingsPage .select2-container .selection
|
||||
{
|
||||
width: 100% !important;
|
||||
display: inline-grid;
|
||||
}
|
||||
|
||||
|
||||
/* Basic style for the div elements */
|
||||
#settingsPage .setting_overriden_by_env {
|
||||
position: relative;
|
||||
/* width: 300px;
|
||||
height: 200px; */
|
||||
background-color: #f3f3f3;
|
||||
border: 1px solid #ccc;
|
||||
margin: 20px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Style for the overlay */
|
||||
#settingsPage .setting_overriden_by_env::after {
|
||||
content: "Overridden with ENV variable";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6); /* semi-transparent black overlay */
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* Devices page */
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
#txtIconFA {
|
||||
.iconPreview {
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
@@ -1110,18 +1178,18 @@ input[readonly] {
|
||||
cursor: -webkit-grab;
|
||||
}
|
||||
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple .select2-selection__choice
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice
|
||||
{
|
||||
background-color:#258744;
|
||||
background-color:#258744 !important;
|
||||
}
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple
|
||||
.select2-container--default .select2-selection--multiple
|
||||
{
|
||||
background-color:#606060;
|
||||
background-color:#606060 !important;
|
||||
}
|
||||
|
||||
.select2-container .select2-dropdown
|
||||
{
|
||||
background-color:#606060;
|
||||
background-color:#606060 !important;
|
||||
}
|
||||
|
||||
.networkPageHelp{
|
||||
@@ -1390,7 +1458,7 @@ input[readonly] {
|
||||
|
||||
opacity: 0.8;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
z-index: 800;
|
||||
}
|
||||
|
||||
.pa_spinner {
|
||||
@@ -1403,7 +1471,7 @@ input[readonly] {
|
||||
padding: 15px;
|
||||
width: 200px;
|
||||
background-color: #fff;
|
||||
z-index: 100;
|
||||
z-index: 801;
|
||||
}
|
||||
|
||||
#loadingSpinner
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
<div class="col-lg-12 col-sm-12 col-xs-12">
|
||||
<!-- <div class="box-transparent"> -->
|
||||
<div id="navDevice" class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs" style="fon t-size:16px;">
|
||||
<ul class="nav nav-tabs" style="font-size:16px;">
|
||||
<li> <a id="tabDetails" href="#panDetails" data-toggle="tab"> <?= lang('DevDetail_Tab_Details');?> </a></li>
|
||||
<li> <a id="tabTools" href="#panTools" data-toggle="tab"> <?= lang('DevDetail_Tab_Tools');?> </a></li>
|
||||
<li> <a id="tabSessions" href="#panSessions" data-toggle="tab"> <?= lang('DevDetail_Tab_Sessions');?> </a></li>
|
||||
@@ -197,8 +197,8 @@
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="txtIconFA"></span>
|
||||
<input class="form-control" id="txtIcon" type="text" value="--" readonly>
|
||||
<span class="input-group-addon iconPreview" id="txtIconPreview" my-customid="txtIconPreview"></span>
|
||||
<input class="form-control" id="txtIcon" my-customid="txtIcon" my-customparams="txtIcon,txtIconPreview" 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">
|
||||
@@ -693,7 +693,6 @@ if ($ENABLED_DARKMODE === True) {
|
||||
|
||||
var pos = -1;
|
||||
var parPeriod = 'Front_Details_Period';
|
||||
var parTab = 'Front_Details_Tab';
|
||||
var parSessionsRows = 'Front_Details_Sessions_Rows';
|
||||
var parEventsRows = 'Front_Details_Events_Rows';
|
||||
var parEventsHide = 'Front_Details_Events_Hide';
|
||||
@@ -736,7 +735,7 @@ function main () {
|
||||
$('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeTabs();
|
||||
initializeTabsNew();
|
||||
initializeiCheck();
|
||||
initializeCombos();
|
||||
initializeDatatables();
|
||||
@@ -756,24 +755,13 @@ function main () {
|
||||
|
||||
// Show device icon as it changes
|
||||
$('#txtIcon').on('change input', function() {
|
||||
updateIconPreview('#txtIcon')
|
||||
updateIconPreview(this)
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function initializeTabs () {
|
||||
// Activate panel
|
||||
$('.nav-tabs a[id='+ tab +']').tab('show');
|
||||
|
||||
// When changed save new current tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
setParameter (parTab, $(e.target).attr('id'));
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function initializeiCheck () {
|
||||
// Blue
|
||||
@@ -1148,7 +1136,7 @@ function initializeCalendar () {
|
||||
showSpinner()
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
updateIconPreview('#txtIcon')
|
||||
updateIconPreview($('#txtIcon'))
|
||||
}, 500);
|
||||
|
||||
hideSpinner()
|
||||
@@ -1457,10 +1445,10 @@ function setDeviceData (direction='', refreshCallback='') {
|
||||
|
||||
// update data to server
|
||||
$.get('php/server/devices.php?action=setDeviceData&mac='+ mac
|
||||
+ '&name=' + encodeURIComponent($('#txtName').val())
|
||||
+ '&owner=' + encodeURIComponent($('#txtOwner').val())
|
||||
+ '&name=' + encodeURIComponent($('#txtName').val().replace(/'/g, ""))
|
||||
+ '&owner=' + encodeURIComponent($('#txtOwner').val().replace(/'/g, ""))
|
||||
+ '&type=' + $('#txtDeviceType').val()
|
||||
+ '&vendor=' + encodeURIComponent($('#txtVendor').val())
|
||||
+ '&vendor=' + encodeURIComponent($('#txtVendor').val().replace(/'/g, ""))
|
||||
+ '&icon=' + encodeURIComponent($('#txtIcon').val())
|
||||
+ '&favorite=' + ($('#chkFavorite')[0].checked * 1)
|
||||
+ '&group=' + encodeURIComponent($('#txtGroup').val())
|
||||
@@ -1679,7 +1667,7 @@ function addAsBase64 () {
|
||||
|
||||
$('#txtIcon').val(iconHtmlBase64);
|
||||
|
||||
updateIconPreview('#txtIcon')
|
||||
updateIconPreview($('#txtIcon'))
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -137,136 +137,70 @@
|
||||
<!-- page script ----------------------------------------------------------- -->
|
||||
<script>
|
||||
var deviceStatus = 'all';
|
||||
var parTableRows = 'Front_Devices_Rows';
|
||||
var parTableOrder = 'Front_Devices_Order';
|
||||
var tableRows = 10;
|
||||
var tableOrder = [[3,'desc'], [0,'asc']];
|
||||
var tableRows = getCookie ("nax_parTableRows") == "" ? 10 : getCookie ("nax_parTableRows") ;
|
||||
var tableOrder = getCookie ("nax_parTableOrder") == "" ? [[3,'desc'], [0,'asc']] : JSON.parse(getCookie ("nax_parTableOrder")) ;
|
||||
|
||||
var tableColumnHide = [];
|
||||
var tableColumnOrder = [];
|
||||
var tableColumnVisible = [];
|
||||
|
||||
|
||||
|
||||
|
||||
// Read parameters & Initialize components
|
||||
callAfterAppInitialized(main)
|
||||
showSpinner();
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function main () {
|
||||
|
||||
//initialize the table headers in the correct order
|
||||
var headersDefaultOrder = [
|
||||
getString('Device_TableHead_Name'),
|
||||
getString('Device_TableHead_Owner'),
|
||||
getString('Device_TableHead_Type'),
|
||||
getString('Device_TableHead_Icon'),
|
||||
getString('Device_TableHead_Favorite'),
|
||||
getString('Device_TableHead_Group'),
|
||||
getString('Device_TableHead_FirstSession'),
|
||||
getString('Device_TableHead_LastSession'),
|
||||
getString('Device_TableHead_LastIP'),
|
||||
getString('Device_TableHead_MAC'),
|
||||
getString('Device_TableHead_Status'),
|
||||
getString('Device_TableHead_MAC_full'),
|
||||
getString('Device_TableHead_LastIPOrder'),
|
||||
getString('Device_TableHead_Rowid'),
|
||||
getString('Device_TableHead_Parent_MAC'),
|
||||
getString('Device_TableHead_Connected_Devices'),
|
||||
getString('Device_TableHead_Location'),
|
||||
getString('Device_TableHead_Vendor'),
|
||||
getString('Device_TableHead_Port'),
|
||||
getString('Device_TableHead_GUID'),
|
||||
getString('Device_TableHead_SyncHubNodeName'),
|
||||
getString('Device_TableHead_NetworkSite'),
|
||||
getString('Device_TableHead_SSID')
|
||||
];
|
||||
//initialize the table headers in the correct order
|
||||
var availableColumns = getSettingOptions("UI_device_columns").split(",");
|
||||
var headersDefaultOrder = availableColumns.map(val => getString(val));
|
||||
var selectedColumns = JSON.parse(getSetting("UI_device_columns").replace(/'/g, '"'));
|
||||
|
||||
// generate default order lists of given length
|
||||
var columnsStr = JSON.stringify(Array.from({ length: headersDefaultOrder.length }, (_, i) => i));
|
||||
tableColumnOrder = Array.from({ length: headersDefaultOrder.length }, (_, i) => i);
|
||||
tableColumnVisible = tableColumnOrder;
|
||||
tableColumnVisible = [];
|
||||
|
||||
handleLoadingDialog()
|
||||
// Initialize tableColumnVisible by including all columns from selectedColumns, preserving their order.
|
||||
tableColumnVisible = selectedColumns.map(column => availableColumns.indexOf(column)).filter(index => index !== -1);
|
||||
|
||||
// Add any columns from availableColumns that are not in selectedColumns to the end.
|
||||
const remainingColumns = availableColumns.map((column, index) => index).filter(index => !tableColumnVisible.includes(index));
|
||||
|
||||
// Combine both arrays.
|
||||
tableColumnOrder = tableColumnVisible.concat(remainingColumns);
|
||||
|
||||
// Generate the full array of numbers from 0 to totalLength - 1 of tableColumnOrder
|
||||
const fullArray = Array.from({ length: tableColumnOrder.length }, (_, i) => i);
|
||||
|
||||
// Filter out the elements already present in inputArray
|
||||
const missingNumbers = fullArray.filter(num => !tableColumnVisible.includes(num));
|
||||
|
||||
// Concatenate the inputArray with the missingNumbers
|
||||
tableColumnOrder = [...tableColumnVisible, ...missingNumbers];
|
||||
|
||||
// render table headers
|
||||
html = '';
|
||||
|
||||
for(index = 0; index < tableColumnOrder.length; index++)
|
||||
{
|
||||
html += '<th>' + headersDefaultOrder[tableColumnOrder[index]] + '</th>';
|
||||
}
|
||||
|
||||
$('#tableDevices tr').html(html);
|
||||
|
||||
// Hide UI elements as per settings
|
||||
// setTimeout(() => {
|
||||
hideUIelements("UI_DEV_SECTIONS")
|
||||
|
||||
// }, 10);
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeDatatable(getUrlAnchor('my_devices'));
|
||||
|
||||
// check if data outdated and show spinner if so
|
||||
handleLoadingDialog()
|
||||
|
||||
|
||||
// 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',',')
|
||||
|
||||
defaultValue = cookieColumnsVisibleStr == "" ? columnsStr : cookieColumnsVisibleStr;
|
||||
|
||||
// get visible columns
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Visible&skipcache', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
// save which columns are in the Devices page visible
|
||||
tableColumnVisible = numberArrayFromString(data);
|
||||
|
||||
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
|
||||
cookieColumnsOrderStr = decodeURI(getCookie("Front_Devices_Columns_Order")).replaceAll('%2C',',')
|
||||
|
||||
defaultValue = cookieColumnsOrderStr == "" ? columnsStr : cookieColumnsOrderStr;
|
||||
|
||||
// get the custom order specified by the user
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Order&skipcache', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
// save the columns order in the Devices page
|
||||
tableColumnOrder = numberArrayFromString(data);
|
||||
|
||||
html = '';
|
||||
|
||||
for(index = 0; index < tableColumnOrder.length; index++)
|
||||
{
|
||||
html += '<th>' + headersDefaultOrder[tableColumnOrder[index]] + '</th>';
|
||||
}
|
||||
|
||||
$('#tableDevices tr').html(html);
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=50¶meter='+ parTableRows, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
|
||||
result = parseInt(result, 10)
|
||||
|
||||
if (Number.isInteger (result) ) {
|
||||
tableRows = result;
|
||||
}
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=[[3,"desc"],[0,"asc"]]¶meter='+ parTableOrder, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
result = JSON.parse(result);
|
||||
|
||||
|
||||
|
||||
if (Array.isArray (result) ) {
|
||||
tableOrder = result;
|
||||
}
|
||||
|
||||
// Initialize components with parameters
|
||||
|
||||
initializeDatatable(getUrlAnchor('my_devices'));
|
||||
|
||||
// check if data outdated and show spinner if so
|
||||
handleLoadingDialog()
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -467,6 +401,11 @@ function initializeDatatable (status) {
|
||||
}
|
||||
|
||||
$.get('api/table_devices.json?nocache=' + Date.now(), function(result) {
|
||||
|
||||
// refresh devices cache
|
||||
devicesListAll_JSON = result["data"]
|
||||
devicesListAll_JSON_str = JSON.stringify(devicesListAll_JSON)
|
||||
setCache('devicesListAll_JSON', devicesListAll_JSON_str)
|
||||
|
||||
// query data
|
||||
getDevicesTotals(result.data);
|
||||
@@ -515,10 +454,6 @@ function initializeDatatable (status) {
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// TODO displayed columns
|
||||
|
||||
|
||||
// Check if the DataTable already exists
|
||||
if ($.fn.dataTable.isDataTable('#tableDevices')) {
|
||||
// The DataTable exists, so destroy it
|
||||
@@ -526,12 +461,12 @@ function initializeDatatable (status) {
|
||||
table.clear().destroy();
|
||||
}
|
||||
|
||||
var table=
|
||||
var table =
|
||||
$('#tableDevices').DataTable({
|
||||
'data' : dataArray["data"],
|
||||
'paging' : true,
|
||||
'lengthChange' : true,
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, 100000], [10, 25, 50, 100, 500, getString('Device_Tablelenght_all')]],
|
||||
'searching' : true,
|
||||
|
||||
'ordering' : true,
|
||||
@@ -679,11 +614,11 @@ function initializeDatatable (status) {
|
||||
|
||||
// Save cookie Rows displayed, and Parameters rows & order
|
||||
$('#tableDevices').on( 'length.dt', function ( e, settings, len ) {
|
||||
setParameter (parTableRows, len);
|
||||
setCookie ("nax_parTableRows", len);
|
||||
} );
|
||||
|
||||
$('#tableDevices').on( 'order.dt', function () {
|
||||
setParameter (parTableOrder, JSON.stringify (table.order()) );
|
||||
setCookie ("nax_parTableOrder", JSON.stringify (table.order()) );
|
||||
setCache ('devicesList', getDevicesFromTable(table) );
|
||||
} );
|
||||
|
||||
@@ -703,8 +638,6 @@ function initializeDatatable (status) {
|
||||
// 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);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 6.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 6.2 KiB |
374
front/img/svg/netalertx_red_1_backup_cleaned.svg
Executable file
374
front/img/svg/netalertx_red_1_backup_cleaned.svg
Executable file
@@ -0,0 +1,374 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="200"
|
||||
height="200"
|
||||
viewBox="0 0 52.916667 52.916668"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="netalertx_red_1_backup_clened.svg"
|
||||
inkscape:export-filename="C:\Users\jokob\netalertx_red_1.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="132.22897"
|
||||
inkscape:cy="118.44039"
|
||||
inkscape:window-width="3440"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer6"
|
||||
units="px"
|
||||
width="50px" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="powermask"
|
||||
id="path-effect51283"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
uri="#mask-powermask-path-effect51283"
|
||||
invert="false"
|
||||
hide_mask="false"
|
||||
background="true"
|
||||
background_color="#ffffffff" />
|
||||
<inkscape:path-effect
|
||||
effect="powermask"
|
||||
id="path-effect51278"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
uri="#mask-powermask-path-effect51278"
|
||||
invert="false"
|
||||
hide_mask="false"
|
||||
background="true"
|
||||
background_color="#ffffffff" />
|
||||
<inkscape:path-effect
|
||||
effect="powermask"
|
||||
id="path-effect51273"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
uri="#mask-powermask-path-effect51273"
|
||||
invert="false"
|
||||
hide_mask="false"
|
||||
background="true"
|
||||
background_color="#ffffffff" />
|
||||
<inkscape:path-effect
|
||||
effect="powermask"
|
||||
id="path-effect48754"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
uri="#mask-powermask-path-effect48754"
|
||||
invert="false"
|
||||
hide_mask="false"
|
||||
background="true"
|
||||
background_color="#ffffffff" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath48972">
|
||||
<path
|
||||
style="fill:#000000;stroke-width:0.280643"
|
||||
id="path48974"
|
||||
width="56.128242"
|
||||
height="56.128246"
|
||||
x="-18.924671"
|
||||
y="-56.198174"
|
||||
transform="rotate(45.438374)"
|
||||
mask="none"
|
||||
sodipodi:type="rect" />
|
||||
</clipPath>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask49405">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:60.8695px;line-height:1.25;font-family:Amiri;-inkscape-font-specification:Amiri;display:inline;stroke-width:1.52174"
|
||||
x="66.930733"
|
||||
y="78.642288"
|
||||
id="text49409"
|
||||
transform="scale(1.4861626,0.67287388)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan49407"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Tw Cen MT';-inkscape-font-specification:'Tw Cen MT';fill:#ffffff;stroke-width:1.52174"
|
||||
x="66.930733"
|
||||
y="78.642288">A</tspan></text>
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath50306">
|
||||
<circle
|
||||
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
|
||||
id="circle50308"
|
||||
cy="26.458334"
|
||||
cx="26.458334"
|
||||
r="26.458334"
|
||||
clip-path="url(#clipPath48972)"
|
||||
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath48972-7">
|
||||
<path
|
||||
style="fill:#000000;stroke-width:0.280643"
|
||||
id="path48974-5"
|
||||
width="56.128242"
|
||||
height="56.128246"
|
||||
x="-18.924671"
|
||||
y="-56.198174"
|
||||
transform="rotate(45.438374)"
|
||||
mask="none"
|
||||
sodipodi:type="rect" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath50306-6">
|
||||
<circle
|
||||
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
|
||||
id="circle50308-5"
|
||||
cy="26.458334"
|
||||
cx="26.458334"
|
||||
r="26.458334"
|
||||
clip-path="url(#clipPath48972)"
|
||||
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
|
||||
</clipPath>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask-powermask-path-effect51273">
|
||||
<path
|
||||
id="mask-powermask-path-effect51273_box"
|
||||
style="fill:#ffffff;fill-opacity:1"
|
||||
d="m 71.788348,33.677177 h 2.00083 v 2.173766 h -2.00083 z" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path51263"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="66.211845"
|
||||
sodipodi:cy="37.490814"
|
||||
sodipodi:rx="3.9464016"
|
||||
sodipodi:ry="1.4616301"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="0.031086059"
|
||||
sodipodi:open="true"
|
||||
sodipodi:arc-type="arc"
|
||||
d="m 70.158247,37.490814 a 3.9464016,1.4616301 0 0 1 -0.0019,0.04543" />
|
||||
</mask>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask-powermask-path-effect51278">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path51267"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="66.211845"
|
||||
sodipodi:cy="37.490814"
|
||||
sodipodi:rx="3.9464016"
|
||||
sodipodi:ry="1.4616301"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="0.031086059"
|
||||
sodipodi:open="true"
|
||||
sodipodi:arc-type="arc" />
|
||||
</mask>
|
||||
<mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
id="mask-powermask-path-effect51283">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path51271"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="66.211845"
|
||||
sodipodi:cy="37.490814"
|
||||
sodipodi:rx="3.9464016"
|
||||
sodipodi:ry="1.4616301"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="0.031086059"
|
||||
sodipodi:open="true"
|
||||
sodipodi:arc-type="arc" />
|
||||
</mask>
|
||||
<filter
|
||||
id="mask-powermask-path-effect51273_inverse"
|
||||
inkscape:label="filtermask-powermask-path-effect51273"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
height="100"
|
||||
width="100"
|
||||
x="-50"
|
||||
y="-50">
|
||||
<feColorMatrix
|
||||
id="mask-powermask-path-effect51273_primitive1"
|
||||
values="1"
|
||||
type="saturate"
|
||||
result="fbSourceGraphic" />
|
||||
<feColorMatrix
|
||||
id="mask-powermask-path-effect51273_primitive2"
|
||||
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
|
||||
in="fbSourceGraphic" />
|
||||
</filter>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Red 1"
|
||||
style="display:none">
|
||||
<circle
|
||||
style="fill:#ff2a2a;stroke-width:0.176318"
|
||||
id="path31-8"
|
||||
cy="26.458334"
|
||||
cx="26.458334"
|
||||
r="26.458334" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Black"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<ellipse
|
||||
style="fill:#000000;stroke-width:0.176146"
|
||||
id="path31"
|
||||
cy="26.51001"
|
||||
cx="26.458334"
|
||||
rx="26.458334"
|
||||
ry="26.406658" />
|
||||
<circle
|
||||
style="display:inline;fill:#ffffff;stroke-width:0.176318"
|
||||
id="path31-89"
|
||||
mask="url(#mask49405)"
|
||||
transform="translate(-99.990036,0.02979629)"
|
||||
r="26.458334"
|
||||
cy="26.458334"
|
||||
cx="126.45834" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="A - Layer 2"
|
||||
style="display:none">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.328992"
|
||||
id="rect48998"
|
||||
width="26.0966"
|
||||
height="6.0620313"
|
||||
x="13.255443"
|
||||
y="41.262722" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="g48055"
|
||||
inkscape:label="Red top"
|
||||
style="display:none;mix-blend-mode:normal">
|
||||
<circle
|
||||
style="mix-blend-mode:normal;fill:#d40000;stroke-width:0.176318"
|
||||
id="circle48752"
|
||||
cy="26.458334"
|
||||
cx="26.458334"
|
||||
r="26.458334"
|
||||
clip-path="url(#clipPath48972)"
|
||||
transform="matrix(1.0038771,0,0.00391255,1.0073928,-0.04603368,-0.1228191)" />
|
||||
<ellipse
|
||||
style="display:inline;mix-blend-mode:normal;fill:#000000;stroke-width:0.43638"
|
||||
id="path50080"
|
||||
clip-path="url(#clipPath50306)"
|
||||
ry="13.739323"
|
||||
rx="16.735666"
|
||||
cy="22.874514"
|
||||
cx="26.36149"
|
||||
transform="translate(0,0.09980904)" />
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path51325"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="16.772207"
|
||||
sodipodi:cy="26.090099"
|
||||
sodipodi:rx="4.1291056"
|
||||
sodipodi:ry="7.6004772"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="0.031086059"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 20.901313,26.090099 a 4.1291056,7.6004772 0 0 1 -0.002,0.236231 l -4.127111,-0.236231 z" />
|
||||
<path
|
||||
style="fill:#d40000"
|
||||
id="path51717"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="26.441042"
|
||||
sodipodi:cy="-26.531424"
|
||||
sodipodi:rx="10.418671"
|
||||
sodipodi:ry="9.5820541"
|
||||
sodipodi:start="0.82219863"
|
||||
sodipodi:end="2.3054129"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 33.532115,-19.511189 a 10.418671,9.5820541 0 0 1 -14.074736,0.09049 l 6.983663,-7.110726 z"
|
||||
transform="matrix(1,0,0.0048047,-0.99998846,0,0)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:0.276214"
|
||||
d="M 145.28835,50.354872 C 127.01317,34.62734 98.057144,30.012421 73.710372,38.947003 c -6.518003,2.391924 -14.288822,6.834002 -19.265958,11.01311 -1.198654,1.006465 -2.270358,1.829935 -2.381565,1.829935 -0.111206,0 -5.210052,-5.102002 -11.33077,-11.337781 L 29.603503,29.114489 30.822139,27.851613 c 0.670251,-0.69458 2.51592,-2.384634 4.101489,-3.755674 C 50.725112,10.43241 69.462577,2.3767456 90.736164,0.10085492 95.380582,-0.39601422 106.33043,-0.31105699 111.03786,0.25837091 133.04363,2.9202648 151.46536,11.26468 167.83762,25.986722 l 3.30701,2.97369 -2.29392,2.320103 c -1.26165,1.276057 -6.58213,6.517685 -11.82329,11.648065 l -9.52936,9.327957 z"
|
||||
id="path52311"
|
||||
transform="scale(0.26458333)" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:0.276214"
|
||||
d="M 86.538548,86.634546 74.145111,73.25799 74.899337,72.758689 c 4.93766,-3.268754 10.138703,-6.508578 16.602198,-7.437693 5.484021,-0.788317 12.228205,-0.984814 16.377135,-0.09119 6.77689,1.459652 11.87156,4.340971 17.02452,7.792011 l 0.97468,0.652765 -1.37124,1.269268 c -0.86863,0.804036 -6.82647,6.676301 -13.34742,13.259175 L 99.423152,99.796276 Z"
|
||||
id="path52350"
|
||||
transform="scale(0.26458333)"
|
||||
inkscape:export-filename="C:\Users\jokob\path52350.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
sodipodi:nodetypes="ccsssscsscc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer6"
|
||||
inkscape:label="Circle"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path50026"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="71.071762"
|
||||
sodipodi:cy="34.677177"
|
||||
sodipodi:rx="1.7174155"
|
||||
sodipodi:ry="5.5907354"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="0.031086059"
|
||||
sodipodi:open="true"
|
||||
sodipodi:arc-type="arc"
|
||||
mask="url(#mask-powermask-path-effect51273)"
|
||||
d="m 72.789178,34.677177 a 1.7174155,5.5907354 0 0 1 -8.3e-4,0.173766"
|
||||
inkscape:path-effect="#path-effect51273" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke-width:0.276214"
|
||||
d="m 151.08883,181.46994 -2.76213,-2.60427 -48.802077,-0.009 -48.802075,-0.009 -2.292573,2.48592 c -1.260915,1.36726 -2.431589,2.48592 -2.601499,2.48592 -0.869396,0 -9.118995,-6.36599 -13.713669,-10.58246 l -2.688104,-2.46684 34.973647,-35.11455 c 19.235503,-19.313 34.922993,-35.39075 35.029879,-35.39075 0.106889,0 16.231201,16.10588 35.663001,35.45326 l 35.33055,35.17705 -2.48592,2.35505 c -3.08951,2.92687 -7.41515,6.40509 -11.09719,8.92319 -1.54594,1.05725 -2.85105,1.91728 -2.90024,1.9112 -0.0492,-0.006 -1.33242,-1.183 -2.8516,-2.61535 z m -38.4631,-38.32188 -13.050732,-13.05073 -13.050727,13.05073 -13.050725,13.05072 h 26.101452 26.101452 z"
|
||||
id="path52389"
|
||||
transform="scale(0.26458333)"
|
||||
inkscape:export-filename="C:\Users\jokob\path52389.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
sodipodi:nodetypes="ccccssscssscsscccccccccc" />
|
||||
<path
|
||||
style="fill:#d40000;stroke-width:0.276214"
|
||||
d="M 86.416478,86.793237 C 73.427951,73.815968 73.387119,73.801376 73.387119,73.801376 c 3.874197,-3.341721 11.025508,-6.981646 17.312424,-8.529335 2.339787,-0.576001 4.881362,-1.25628 8.810591,-1.259564 4.438736,-0.0037 8.292516,0.857843 13.253396,2.535104 4.59135,1.552325 7.8315,3.224336 11.49958,5.934101 l 1.61476,1.192897 -2.31005,2.336325 c -1.27053,1.284978 -7.22284,7.16236 -13.22736,13.060849 L 99.423152,99.796276 C 95.128284,95.409033 87.282899,87.658907 86.416478,86.793237 Z"
|
||||
id="path52465"
|
||||
transform="scale(0.26458333)"
|
||||
sodipodi:nodetypes="sssssscsscs" />
|
||||
<path
|
||||
style="fill:#d40000;stroke-width:0.074168"
|
||||
d="M 38.412677,13.39572 C 34.322163,9.945267 28.437517,8.4874766 22.684204,9.4993379 19.419721,10.073478 16.752307,11.410793 13.835187,13.872492 l -0.14691,0.126732 -0.587936,-0.661605 c -0.268568,-0.30222 -1.619514,-1.65761 -2.963235,-3.048642 L 7.7265561,7.8632145 7.9975963,7.5868118 C 9.8344314,5.713635 13.005888,3.476019 15.380049,2.3878744 20.659765,-0.03196726 26.24205,-0.73479764 31.856076,0.42838695 36.599757,1.4112419 40.746004,3.5106537 44.46876,7.1557672 l 0.709881,0.6950753 -0.663694,0.69037 C 44.080041,8.9935983 42.672626,10.391271 41.3963,11.655819 L 39.075708,13.955 Z"
|
||||
id="path52504"
|
||||
inkscape:export-filename="C:\Users\jokob\path52504.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
sodipodi:nodetypes="ssscsccsssscsscs" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -78,7 +78,7 @@ if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Net Alert X | Log in</title>
|
||||
<title>NetAlert X | Log in</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">
|
||||
<!-- Bootstrap 3.3.7 -->
|
||||
@@ -104,7 +104,7 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<body class="hold-transition login-page">
|
||||
<div class="login-box login-custom">
|
||||
<div class="login-logo">
|
||||
<a href="/index2.php">Net <b>Alert</b><sup>x</sup></a>
|
||||
<a href="/index2.php">Net<b>Alert</b><sup>x</sup></a>
|
||||
</div>
|
||||
<!-- /.login-logo -->
|
||||
<div class="login-box-body">
|
||||
|
||||
@@ -12,7 +12,7 @@ var timerRefreshData = ''
|
||||
|
||||
var emptyArr = ['undefined', "", undefined, null, 'null'];
|
||||
var UI_LANG = "English";
|
||||
const allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "zh_cn"]; // needs to be same as in lang.php
|
||||
const allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "pt_br", "tr_tr", "zh_cn", "cs_cz"]; // needs to be same as in lang.php
|
||||
var settingsJSON = {}
|
||||
|
||||
|
||||
@@ -212,7 +212,8 @@ function cacheStrings() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// Create a promise for each language
|
||||
const languagePromises = allLanguages.map((language_code) => {
|
||||
languagesToLoad = ['en_us', getLangCode()]
|
||||
const languagePromises = languagesToLoad.map((language_code) => {
|
||||
return new Promise((resolveLang, rejectLang) => {
|
||||
// Fetch core strings and translations
|
||||
|
||||
@@ -267,6 +268,29 @@ function cacheStrings() {
|
||||
function getString(key) {
|
||||
|
||||
function fetchString(key) {
|
||||
|
||||
lang_code = getLangCode();
|
||||
|
||||
let result = getCache(`pia_lang_${key}_${lang_code}`, true);
|
||||
|
||||
if (isEmpty(result)) {
|
||||
result = getCache(`pia_lang_${key}_en_us`, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isAppInitialized()) {
|
||||
return fetchString(key);
|
||||
} else {
|
||||
callAfterAppInitialized(() => fetchString(key));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Get current language ISO code
|
||||
function getLangCode() {
|
||||
|
||||
UI_LANG = getSetting("UI_LANG");
|
||||
|
||||
let lang_code = 'en_us';
|
||||
@@ -305,22 +329,12 @@ function getString(key) {
|
||||
case 'Chinese (zh_cn)':
|
||||
lang_code = 'zh_cn';
|
||||
break;
|
||||
case 'Czech (cs_cz)':
|
||||
lang_code = 'cs_cz';
|
||||
break;
|
||||
}
|
||||
|
||||
let result = getCache(`pia_lang_${key}_${lang_code}`, true);
|
||||
|
||||
if (isEmpty(result)) {
|
||||
result = getCache(`pia_lang_${key}_en_us`, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isAppInitialized()) {
|
||||
return fetchString(key);
|
||||
} else {
|
||||
callAfterAppInitialized(() => fetchString(key));
|
||||
}
|
||||
return lang_code;
|
||||
}
|
||||
|
||||
|
||||
@@ -396,6 +410,7 @@ function handle_locked_DB(data)
|
||||
showSpinner()
|
||||
|
||||
setTimeout(function() {
|
||||
console.warn("Database locked - reload")
|
||||
location.reload();
|
||||
}, 5000);
|
||||
}
|
||||
@@ -615,17 +630,11 @@ function debugTimer () {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function secondsSincePageLoad() {
|
||||
// Get the current time
|
||||
var currentTime = Date.now();
|
||||
|
||||
// Get the time when the page was loaded
|
||||
var pageLoadTime = performance.timeOrigin;
|
||||
|
||||
// Calculate the difference in milliseconds
|
||||
var timeDifference = currentTime - pageLoadTime;
|
||||
// Get the current time since the page was loaded
|
||||
var timeSincePageLoad = performance.now();
|
||||
|
||||
// Convert milliseconds to seconds
|
||||
var secondsAgo = Math.floor(timeDifference / 1000);
|
||||
var secondsAgo = Math.floor(timeSincePageLoad / 1000);
|
||||
|
||||
return secondsAgo;
|
||||
}
|
||||
@@ -1131,6 +1140,54 @@ function arraysContainSameValues(arr1, arr2) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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()
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// apply dark mode
|
||||
|
||||
$(document).ready(function() {
|
||||
// Assume getSetting is a function that returns true or false for dark mode
|
||||
if (getSetting("UI_dark_mode") === "True") {
|
||||
// Add the dark mode stylesheet
|
||||
setCookie("UI_dark_mode", "True")
|
||||
$('head').append('<link rel="stylesheet" href="css/dark-patch.css">');
|
||||
// Set the background image for dark mode
|
||||
$('body').attr('style', 'background-image: url(\'img/boxed-bg-dark.png\');');
|
||||
} else {
|
||||
setCookie("UI_dark_mode", "False")
|
||||
// Set the background image for light mode
|
||||
$('body').attr('style', 'background-image: url(\'img/background.png\');');
|
||||
}
|
||||
});
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// initialize
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -1141,7 +1198,7 @@ const sessionStorageKey = "myScriptExecuted_common_js";
|
||||
var completedCalls = []
|
||||
var completedCalls_final = ['cacheSettings', 'cacheStrings', 'cacheDevices'];
|
||||
var completedCallsCount = 0;
|
||||
var completedCallsCount_final = allLanguages.length + 2; // number of language files + cacheDevices + cacheSettings
|
||||
var completedCallsCount_final;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Clearing all the caches
|
||||
@@ -1150,8 +1207,9 @@ function clearCache() {
|
||||
sessionStorage.clear();
|
||||
localStorage.clear();
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
console.warn("clearChache called");
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -1196,7 +1254,11 @@ function callAfterAppInitialized(callback) {
|
||||
// Check if the code has been executed before by checking sessionStorage
|
||||
function isAppInitialized() {
|
||||
// return arraysContainSameValues(getCache("completedCalls").split(',').filter(Boolean), completedCalls_final);
|
||||
return (parseInt(getCache("completedCallsCount")) == completedCallsCount_final);
|
||||
|
||||
// loading settings + 1 (or 2 language files if not english) + device cache.
|
||||
completedCallsCount_final = getLangCode() == 'en_us' ? 3 : 4 ;
|
||||
|
||||
return (parseInt(getCache("completedCallsCount")) >= completedCallsCount_final);
|
||||
}
|
||||
|
||||
// Define a function that will execute the code only once
|
||||
@@ -1288,6 +1350,7 @@ setTimeout(() => {
|
||||
// page refresh if configured
|
||||
const refreshTime = getSetting("UI_REFRESH");
|
||||
if (refreshTime && refreshTime !== "0" && refreshTime !== "") {
|
||||
console.log("Refreshing page becasue UI_REFRESH setting enabled.");
|
||||
newTimerRefreshData(clearCache, parseInt(refreshTime)*1000);
|
||||
}
|
||||
|
||||
|
||||
@@ -295,6 +295,7 @@ function checkNotification() {
|
||||
console.log(response);
|
||||
// After marking the notification as read, check for the next one
|
||||
checkNotification();
|
||||
hideSpinner();
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("Error marking notification as read:", status, error);
|
||||
|
||||
@@ -304,6 +304,54 @@ function removeAllOptions(element) {
|
||||
$(`#${$(element).attr("my-input-to")}`).empty();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Add all options
|
||||
function selectAll(element) {
|
||||
settingsChanged();
|
||||
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
// Iterate over each option within the select element
|
||||
selectElement.find('option').each(function() {
|
||||
// Mark each option as selected
|
||||
$(this).prop('selected', true);
|
||||
});
|
||||
|
||||
// Trigger the 'change' event to notify Bootstrap Select of the changes
|
||||
selectElement.trigger('change');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// UN-Select All
|
||||
function unselectAll(element) {
|
||||
settingsChanged();
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
// Iterate over each option within the select element
|
||||
selectElement.find('option').each(function() {
|
||||
// Unselect each option
|
||||
$(this).prop('selected', false);
|
||||
});
|
||||
|
||||
// Trigger the 'change' event to notify Bootstrap Select of the changes
|
||||
selectElement.trigger('change');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Trigger change to open up the dropdown filed
|
||||
function selectChange(element) {
|
||||
settingsChanged();
|
||||
// Get the <select> element with the class 'deviceSelector'
|
||||
// var selectElement = $('.deviceSelector select');
|
||||
var selectElement = $(`#${$(element).attr("my-input-to")}`);
|
||||
|
||||
selectElement.parent().find("input").focus().click();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Function to initialize remove functionality on select options
|
||||
|
||||
@@ -437,8 +485,6 @@ function filterRows(inputText) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
// Event listener for input change
|
||||
$("#settingsSearch").on("input", function () {
|
||||
@@ -568,6 +614,10 @@ function applyTransformers(val, transformers) {
|
||||
val = btoa(val);
|
||||
}
|
||||
break;
|
||||
case "getString":
|
||||
// no change
|
||||
val = val;
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown transformer: ${transformer}`);
|
||||
}
|
||||
@@ -590,6 +640,10 @@ function reverseTransformers(val, transformers) {
|
||||
val = atob(val);
|
||||
}
|
||||
break;
|
||||
case "getString":
|
||||
// retrieve string
|
||||
val = getString(val);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown transformer: ${transformer}`);
|
||||
}
|
||||
@@ -604,6 +658,7 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
let inputType = "text";
|
||||
let readOnly = "";
|
||||
let isMultiSelect = false;
|
||||
let isOrdeable = false;
|
||||
let cssClasses = "";
|
||||
let placeholder = "";
|
||||
let suffix = "";
|
||||
@@ -612,7 +667,11 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
let valRes = val;
|
||||
let sourceIds = [];
|
||||
let getStringKey = "";
|
||||
let onClick = "alert('Not implemented');";
|
||||
let onClick = "console.log('onClick - Not implemented');";
|
||||
let onChange = "console.log('onChange - Not implemented');";
|
||||
let customParams = "";
|
||||
let customId = "";
|
||||
|
||||
|
||||
elementOptions.forEach((option) => {
|
||||
if (option.prefillValue) {
|
||||
@@ -627,6 +686,9 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
if (option.multiple === "true") {
|
||||
isMultiSelect = true;
|
||||
}
|
||||
if (option.ordeable === "true") {
|
||||
isOrdeable = true;
|
||||
}
|
||||
if (option.editable === "true") {
|
||||
editable = true;
|
||||
}
|
||||
@@ -653,6 +715,15 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
if (option.onClick) {
|
||||
onClick = option.onClick;
|
||||
}
|
||||
if (option.onChange) {
|
||||
onChange = option.onChange;
|
||||
}
|
||||
if (option.customParams) {
|
||||
customParams = option.customParams;
|
||||
}
|
||||
if (option.customId) {
|
||||
customId = option.customId;
|
||||
}
|
||||
});
|
||||
|
||||
if (transformers.includes("sha256")) {
|
||||
@@ -663,6 +734,7 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
inputType,
|
||||
readOnly,
|
||||
isMultiSelect,
|
||||
isOrdeable,
|
||||
cssClasses,
|
||||
placeholder,
|
||||
suffix,
|
||||
@@ -672,6 +744,9 @@ const handleElementOptions = (codeName, elementOptions, transformers, val) => {
|
||||
valRes,
|
||||
getStringKey,
|
||||
onClick,
|
||||
onChange,
|
||||
customParams,
|
||||
customId
|
||||
};
|
||||
};
|
||||
|
||||
@@ -698,8 +773,9 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
|
||||
resultArray = []
|
||||
selectedArray = []
|
||||
cssClass = ""
|
||||
|
||||
|
||||
// determine if options or values are used in teh listing
|
||||
// determine if options or values are used in the listing
|
||||
if (valuesArray.length > 0 && options.length > 0){
|
||||
|
||||
// multiselect list -> options only + selected the ones in valuesArray
|
||||
@@ -717,21 +793,31 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
|
||||
resultArray = options;
|
||||
}
|
||||
|
||||
|
||||
// Create a map to track the index of each item in valuesArray
|
||||
const orderMap = new Map(valuesArray.map((item, index) => [item, index]));
|
||||
|
||||
// Sort resultArray based on the order in valuesArray
|
||||
resultArray.sort((a, b) => {
|
||||
const indexA = orderMap.has(a.id) ? orderMap.get(a.id) : valuesArray.length;
|
||||
const indexB = orderMap.has(b.id) ? orderMap.get(b.id) : valuesArray.length;
|
||||
return indexA - indexB;
|
||||
});
|
||||
|
||||
resultArray.forEach(function(item) {
|
||||
let labelName = item.name;
|
||||
|
||||
labelName = item.name
|
||||
|
||||
if(labelName != '❌None')
|
||||
{
|
||||
labelName = reverseTransformers(labelName, transformers)
|
||||
if (labelName !== '❌None') {
|
||||
labelName = reverseTransformers(labelName, transformers);
|
||||
}
|
||||
|
||||
// needs to happen always if options ued as source
|
||||
let selected = options.length != 0 && valuesArray.includes(item.id) ? 'selected' : '';
|
||||
// Always include selected if options are used as a source
|
||||
let selected = options.length !== 0 && valuesArray.includes(item.id) ? 'selected' : '';
|
||||
|
||||
optionsHtml += `<option class="${cssClass}" value="${item.id}" ${selected}>${labelName}</option>`;
|
||||
});
|
||||
|
||||
|
||||
// Place the resulting HTML into the specified placeholder div
|
||||
$("#" + placeholder).replaceWith(optionsHtml);
|
||||
}
|
||||
|
||||
@@ -68,54 +68,65 @@ function initDeviceSelectors(devicesListAll_JSON) {
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
// Updates the icon preview
|
||||
function updateIconPreview(elem) {
|
||||
// Retrieve and parse custom parameters from the element
|
||||
let params = $(elem).attr("my-customparams")?.split(',').map(param => param.trim());
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Hide elements on the page based on the supplied setting
|
||||
function hideUIelements(settingKey) {
|
||||
// console.log(params);
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
});
|
||||
if (params && params.length >= 2) {
|
||||
var inputElementID = params[0];
|
||||
var targetElementID = params[1];
|
||||
} else {
|
||||
console.error("Invalid parameters passed to updateIconPreview function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the input element using the inputElementID
|
||||
let iconInput = $("#" + inputElementID);
|
||||
|
||||
if (iconInput.length === 0) {
|
||||
console.error("Icon input element not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the initial value and update the target element
|
||||
let value = iconInput.val();
|
||||
if (!value) {
|
||||
console.error("Input value is empty or not defined");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetElementID) {
|
||||
targetElementID = "txtIcon";
|
||||
}
|
||||
|
||||
// Check if the target element exists, if not find an element with matching custom attribute
|
||||
let targetElement = $('#' + targetElementID);
|
||||
if (targetElement.length === 0) {
|
||||
// Look for an element with my-custom-id attribute equal to targetElementID
|
||||
targetElement = $('[my-customid="' + targetElementID + '"]');
|
||||
if (targetElement.length === 0) {
|
||||
console.error("Neither target element with ID nor element with custom attribute found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the target element with decoded base64 value
|
||||
targetElement.html(atob(value));
|
||||
|
||||
// Add event listener to update the icon on input change
|
||||
iconInput.on('change input', function () {
|
||||
let newValue = $(this).val();
|
||||
$('#' + targetElementID).html(atob(newValue));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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))
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Generic function to copy text to clipboard
|
||||
@@ -249,6 +260,7 @@ function initSelect2() {
|
||||
|
||||
// --------------------------------------------------------
|
||||
//Initialize Select2 Elements and make them sortable
|
||||
|
||||
$(function () {
|
||||
// Iterate over each Select2 dropdown
|
||||
$('.select2').each(function() {
|
||||
@@ -283,10 +295,15 @@ function initSelect2() {
|
||||
}
|
||||
}
|
||||
|
||||
// try to initialize select2
|
||||
setTimeout(() => {
|
||||
initSelect2()
|
||||
}, 500);
|
||||
// init select2 after dom laoded
|
||||
window.addEventListener("load", function() {
|
||||
// try to initialize select2
|
||||
setTimeout(() => {
|
||||
initSelect2()
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
console.log("init ui_components.js")
|
||||
@@ -1034,7 +1034,7 @@ var mouse = $.widget("ui.mouse", {
|
||||
return this.mouseDelayMet;
|
||||
},
|
||||
|
||||
// These are placeholder methods, to be overriden by extending plugin
|
||||
// These are placeholder methods, to be overridden by extending plugin
|
||||
_mouseStart: function(/* event */) {},
|
||||
_mouseDrag: function(/* event */) {},
|
||||
_mouseStop: function(/* event */) {},
|
||||
|
||||
0
front/log/.gitignore
vendored
Normal file → Executable file
0
front/log/.gitignore
vendored
Normal file → Executable file
@@ -11,25 +11,7 @@
|
||||
# cvc90 2023 https://github.com/cvc90 GNU GPLv3 #
|
||||
#---------------------------------------------------------------------------------#
|
||||
|
||||
// Skin selector config ----------------------------------------------------
|
||||
//
|
||||
// For security reasons, new language files must be entered into this array.
|
||||
// The files in the language directory are compared with this array and only
|
||||
// then accepted.
|
||||
//
|
||||
$pia_installed_skins = array('skin-black-light',
|
||||
'skin-black',
|
||||
'skin-blue-light',
|
||||
'skin-blue',
|
||||
'skin-green-light',
|
||||
'skin-green',
|
||||
'skin-purple-light',
|
||||
'skin-purple',
|
||||
'skin-red-light',
|
||||
'skin-red',
|
||||
'skin-yellow-light',
|
||||
'skin-yellow');
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
?>
|
||||
@@ -38,7 +20,7 @@ $pia_installed_skins = array('skin-black-light',
|
||||
require 'php/templates/header.php';
|
||||
?>
|
||||
<!-- Page ------------------------------------------------------------------ -->
|
||||
<div class="content-wrapper">
|
||||
<div class="content-wrapper" id="maintenancePage">
|
||||
|
||||
<!-- Content header--------------------------------------------------------- -->
|
||||
<section class="content-header">
|
||||
@@ -91,34 +73,6 @@ if (count($latestfiles) > 0)
|
||||
$latestbackup_date = date ("Y-m-d H:i:s", filemtime($latestbackup));
|
||||
}
|
||||
|
||||
|
||||
// Skin selector -----------------------------------------------------------------
|
||||
|
||||
if (isset($_POST['submit']) && submit && isset($_POST['skinselector_set'])) {
|
||||
$pia_skin_set_dir = '../db/';
|
||||
$pia_skin_selector = htmlspecialchars($_POST['skinselector']);
|
||||
if (in_array($pia_skin_selector, $pia_installed_skins)) {
|
||||
foreach ($pia_installed_skins as $file) {
|
||||
unlink ($pia_skin_set_dir.'/setting_'.$file);
|
||||
}
|
||||
foreach ($pia_installed_skins as $file) {
|
||||
if (file_exists($pia_skin_set_dir.'/setting_'.$file)) {
|
||||
$pia_skin_error = True;
|
||||
break;
|
||||
} else {
|
||||
$pia_skin_error = False;
|
||||
}
|
||||
}
|
||||
if ($pia_skin_error == False) {
|
||||
$testskin = fopen($pia_skin_set_dir.'setting_'.$pia_skin_selector, 'w');
|
||||
$pia_skin_test = '';
|
||||
echo("<meta http-equiv='refresh' content='1'>");
|
||||
} else {
|
||||
$pia_skin_test = '';
|
||||
echo("<meta http-equiv='refresh' content='1'>");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Table sizes -----------------------------------------------------------------
|
||||
|
||||
$tableSizesHTML = "";
|
||||
@@ -142,10 +96,6 @@ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
||||
$db->close();
|
||||
|
||||
|
||||
|
||||
|
||||
// Language selector -----------------------------------------------------------------
|
||||
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
@@ -219,13 +169,7 @@ $db->close();
|
||||
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active">
|
||||
<a id="tab_Settings_id" href="#tab_Settings" data-toggle="tab">
|
||||
<i class="fa fa-cogs"></i>
|
||||
<?= lang('Maintenance_Tools_Tab_UISettings');?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<li class="active">
|
||||
<a id="tab_DBTools_id" href="#tab_DBTools" data-toggle="tab">
|
||||
<i class="fa fa-toolbox"></i>
|
||||
<?= lang('Maintenance_Tools_Tab_Tools');?>
|
||||
@@ -251,84 +195,7 @@ $db->close();
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tab_Settings">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" style="text-align: center;">
|
||||
<form method="post" action="maintenance.php">
|
||||
<div style="display: inline-block; text-align: center;">
|
||||
<select name="skinselector" class="form-control bg-green" style="width:160px; margin-bottom:5px;">
|
||||
<option value=""><?= lang('Maintenance_themeselector_empty');?></option>
|
||||
<option value="skin-black-light">black light</option>
|
||||
<option value="skin-black">black</option>
|
||||
<option value="skin-blue-light">blue light</option>
|
||||
<option value="skin-blue">blue</option>
|
||||
<option value="skin-green-light">green light</option>
|
||||
<option value="skin-green">green</option>
|
||||
<option value="skin-purple-light">purple light</option>
|
||||
<option value="skin-purple">purple</option>
|
||||
<option value="skin-red-light">red light</option>
|
||||
<option value="skin-red">red</option>
|
||||
<option value="skin-yellow-light">yellow light</option>
|
||||
<option value="skin-yellow">yellow</option>
|
||||
</select></div>
|
||||
<div style="display: block;"><input type="submit" name="skinselector_set" value="<?= lang('Maintenance_themeselector_apply');?>" class="btn bg-green" style="width:160px;">
|
||||
<?php // echo $pia_skin_test; ?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="db_info_table_cell" style="padding: 10px; height:40px; text-align:left; vertical-align: middle;">
|
||||
<?= lang('Maintenance_themeselector_text'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a">
|
||||
<button type="button" class="btn bg-green dbtools-button" id="btnToggleDarkmode" onclick="askToggleDarkmode()"><?= lang('Maintenance_Tool_darkmode');?></button>
|
||||
</div>
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_darkmode_text');?></div>
|
||||
</div>
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a">
|
||||
<div class="form-group" >
|
||||
<div class="input-group" >
|
||||
<select id="columnsSelect" class="form-control select2 select2-hidden-accessible" multiple="" style="width: 100%;" tabindex="-1" aria-hidden="true">
|
||||
<option value="0"><?= lang('Device_TableHead_Name');?></option>
|
||||
<option value="1"><?= lang('Device_TableHead_Owner');?></option>
|
||||
<option value="2"><?= lang('Device_TableHead_Type');?></option>
|
||||
<option value="3"><?= lang('Device_TableHead_Icon');?></option>
|
||||
<option value="4"><?= lang('Device_TableHead_Favorite');?></option>
|
||||
<option value="5"><?= lang('Device_TableHead_Group');?></option>
|
||||
<option value="6"><?= lang('Device_TableHead_FirstSession');?></option>
|
||||
<option value="7"><?= lang('Device_TableHead_LastSession');?></option>
|
||||
<option value="8"><?= lang('Device_TableHead_LastIP');?></option>
|
||||
<option value="9"><?= lang('Device_TableHead_MAC');?></option>
|
||||
<option value="10"><?= lang('Device_TableHead_Status');?></option>
|
||||
<option value="11"><?= lang('Device_TableHead_MAC_full');?></option>
|
||||
<option value="12"><?= lang('Device_TableHead_LastIPOrder');?></option>
|
||||
<option value="13"><?= lang('Device_TableHead_Rowid');?></option>
|
||||
<option value="14"><?= lang('Device_TableHead_Parent_MAC');?></option>
|
||||
<option value="15"><?= lang('Device_TableHead_Connected_Devices');?></option>
|
||||
<option value="16"><?= lang('Device_TableHead_Location');?></option>
|
||||
<option value="17"><?= lang('Device_TableHead_Vendor');?></option>
|
||||
<option value="18"><?= lang('Device_TableHead_Port');?></option>
|
||||
<option value="19"><?= lang('Device_TableHead_GUID');?></option>
|
||||
<option value="20"><?= lang('Device_TableHead_SyncHubNodeName');?></option>
|
||||
<option value="21"><?= lang('Device_TableHead_NetworkSite');?></option>
|
||||
<option value="22"><?= lang('Device_TableHead_SSID');?></option>
|
||||
</select>
|
||||
<span class="input-group-addon"><i title="<?= lang('Gen_Save');?>" class="fa fa-save pointer" onclick="saveSelectedColumns();"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="db_tools_table_cell_b"><?= lang('Maintenance_Tool_displayed_columns_text');?></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="tab_DBTools">
|
||||
<div class="tab-pane active" id="tab_DBTools">
|
||||
<div class="db_info_table">
|
||||
<div class="db_info_table_row">
|
||||
<div class="db_tools_table_cell_a" >
|
||||
@@ -487,7 +354,7 @@ $db->close();
|
||||
<script>
|
||||
|
||||
var emptyArr = ['undefined', "", undefined, null];
|
||||
var selectedTab = 'tab_Settings_id';
|
||||
var selectedTab = 'tab_DBTools_id';
|
||||
|
||||
initializeTabs();
|
||||
|
||||
@@ -713,42 +580,6 @@ function ImportPastedCSV()
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Switch Darkmode
|
||||
function askToggleDarkmode() {
|
||||
// Ask
|
||||
showModalWarning('<?= lang('Maintenance_Tool_darkmode_noti');?>', '<?= lang('Maintenance_Tool_darkmode_noti_text');?>',
|
||||
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Switch');?>', 'ToggleDarkmode');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
function ToggleDarkmode()
|
||||
{
|
||||
// get parameter Front_Dark_Mode_Enabled value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=false&expireMinutes=525600¶meter=Front_Dark_Mode_Enabled', function(data) {
|
||||
var result = JSON.parse(data);
|
||||
if (result) {
|
||||
darkModeEnabled = result == 'true';
|
||||
|
||||
// invert value
|
||||
darkModeEnabled = !darkModeEnabled;
|
||||
|
||||
// save inverted value
|
||||
$.get('php/server/parameters.php?action=set¶meter=Front_Dark_Mode_Enabled&expireMinutes=525600&value='+ darkModeEnabled,
|
||||
function(data) {
|
||||
if (data != "OK") {
|
||||
showMessage (data);
|
||||
setTimeout(function (){location.reload()}, 1000);
|
||||
|
||||
} else {
|
||||
showMessage (data);
|
||||
};
|
||||
} );
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// Clean log file
|
||||
@@ -801,122 +632,56 @@ function scrollDown() {
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Manage displayed columns
|
||||
// --------------------------------------------------------
|
||||
colDefaultOrder = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17'];
|
||||
colDefaultOrderTxt = '[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]';
|
||||
|
||||
|
||||
function saveSelectedColumns () {
|
||||
$.get('php/server/parameters.php?action=set&expireMinutes=525600&value=['+ $('#columnsSelect').val().toString() +']¶meter=Front_Devices_Columns_Visible', function(data) {
|
||||
// save full order of all columns to simplify mapping later on
|
||||
|
||||
colDisplayed = $('#columnsSelect').val();
|
||||
|
||||
colNewOrder = colDisplayed;
|
||||
|
||||
// append the remaining columns in the previous order
|
||||
for(i = 0; i < colDefaultOrder.length; i++)
|
||||
{
|
||||
if(!colDisplayed.includes(colDefaultOrder[i]))
|
||||
{
|
||||
colNewOrder.push(colDefaultOrder[i])
|
||||
}
|
||||
}
|
||||
|
||||
// save the setting in the DB
|
||||
$.get('php/server/parameters.php?action=set&expireMinutes=525600&value=['+ colNewOrder.toString() +']¶meter=Front_Devices_Columns_Order', function(data) {
|
||||
|
||||
showMessage(data);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
function initializeSelectedColumns () {
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+colDefaultOrderTxt+'¶meter=Front_Devices_Columns_Visible', function(data) {
|
||||
|
||||
handle_locked_DB(data)
|
||||
|
||||
tableColumnShow = numberArrayFromString(data);
|
||||
|
||||
for(i=0; i < tableColumnShow.length; i++)
|
||||
{
|
||||
// create the option and append to Select2
|
||||
var option = new Option($('#columnsSelect option[value='+tableColumnShow[i]+']').html(), tableColumnShow[i] , true, true);
|
||||
|
||||
$("#columnsSelect").append(option).trigger('change');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// General initialization
|
||||
// --------------------------------------------------------
|
||||
function initializeTabs () {
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
key = "activeMaintenanceTab"
|
||||
function initializeTabs() {
|
||||
setTimeout(() => {
|
||||
const key = "activeMaintenanceTab";
|
||||
|
||||
// default selection
|
||||
selectedTab = "tab_Settings"
|
||||
let selectedTab = "tab_DBTools_id";
|
||||
|
||||
// the #target from the url
|
||||
target = window.location.hash.substr(1)
|
||||
// the #target from the URL
|
||||
let target = window.location.hash.substr(1);
|
||||
|
||||
|
||||
console.log(selectedTab);
|
||||
|
||||
// get only the part between #...?
|
||||
if(target.includes('?'))
|
||||
{
|
||||
target = target.split('?')[0]
|
||||
if (target.includes('?')) {
|
||||
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
|
||||
if (target) {
|
||||
selectedTab = target.endsWith("_id") ? target : `${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);
|
||||
// get the tab id from the cookie (already overridden by the target)
|
||||
const cachedTab = getCache(key);
|
||||
if (cachedTab && !emptyArr.includes(cachedTab)) {
|
||||
selectedTab = cachedTab;
|
||||
}
|
||||
|
||||
// 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'))
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', (e) => {
|
||||
const newTabId = $(e.target).attr('id');
|
||||
setCache(key, newTabId);
|
||||
});
|
||||
|
||||
// events on tab change
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
var target = $(e.target).attr("href") // activated tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', (e) => {
|
||||
const newTarget = $(e.target).attr("href"); // activated tab
|
||||
});
|
||||
|
||||
hideSpinner();
|
||||
|
||||
}, 50);
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Logs render functionality
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -936,7 +701,7 @@ function toggleAutoRefresh() {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Manages thefilter application
|
||||
// Manages the filter application on the logs
|
||||
function applyFilter() {
|
||||
const filterText = $("#logsFilter").val().toLowerCase();
|
||||
|
||||
@@ -982,19 +747,20 @@ function renderLogs(customData) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Init
|
||||
window.onload = function asyncFooter()
|
||||
{
|
||||
initializeSelectedColumns();
|
||||
window.onload = function asyncFooter() {
|
||||
renderLogs();
|
||||
|
||||
// initializeTabs();
|
||||
|
||||
$("#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>');
|
||||
try {
|
||||
$("#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://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>');
|
||||
|
||||
}
|
||||
$("#lastDockerUpdate").append(
|
||||
'<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>');
|
||||
} catch (error) {
|
||||
console.error('Failed to load GitHub badges:', error);
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<h3 class="box-title"><?= lang('Gen_Selected_Devices');?></h3>
|
||||
|
||||
</div>
|
||||
<div class="deviceSelector col-md-9" style="z-index:5"></div>
|
||||
<div class="deviceSelector col-md-9 col-sm-12" style="z-index:5"></div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<button type="button" class="btn btn-default" onclick="markAllSelected()">
|
||||
@@ -101,23 +101,25 @@
|
||||
for (let j = i * elementsPerColumn; j < Math.min((i + 1) * elementsPerColumn, columns.length); j++) {
|
||||
|
||||
const setTypeObject = JSON.parse(columns[j].Type.replace(/'/g, '"'));
|
||||
// console.log(setTypeObject); 🔽
|
||||
// const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1]
|
||||
|
||||
// get the element with the input value(s)
|
||||
let elementsWithInputValue = setTypeObject.elements.filter(element => element.elementHasInputValue === 1);
|
||||
let elements = setTypeObject.elements.filter(element => element.elementHasInputValue === 1);
|
||||
|
||||
// if none found, take last
|
||||
if(elementsWithInputValue.length == 0)
|
||||
if(elements.length == 0)
|
||||
{
|
||||
elementsWithInputValue = setTypeObject.elements[setTypeObject.elements.length - 1]
|
||||
elementWithInputValue = setTypeObject.elements[setTypeObject.elements.length - 1]
|
||||
} else
|
||||
{
|
||||
elementWithInputValue = elements[0]
|
||||
}
|
||||
|
||||
const { elementType, elementOptions = [], transformers = [] } = elementsWithInputValue;
|
||||
const { elementType, elementOptions = [], transformers = [] } = elementWithInputValue;
|
||||
const {
|
||||
inputType,
|
||||
readOnly,
|
||||
isMultiSelect,
|
||||
isOrdeable,
|
||||
cssClasses,
|
||||
placeholder,
|
||||
suffix,
|
||||
@@ -126,26 +128,28 @@
|
||||
editable,
|
||||
valRes,
|
||||
getStringKey,
|
||||
onClick
|
||||
onClick,
|
||||
onChange,
|
||||
customParams,
|
||||
customId
|
||||
} = handleElementOptions('none', elementOptions, transformers, val = "");
|
||||
|
||||
// console.log(setTypeObject);
|
||||
// console.log(inputType);
|
||||
|
||||
// render based on element type
|
||||
if (elementsWithInputValue.elementType === 'select') {
|
||||
if (elementType === 'select') {
|
||||
|
||||
targetLocation = columns[j].Code_Name + "_generateSetOptions"
|
||||
|
||||
generateOptionsOrSetOptions(columns[j].Code_Name, [], targetLocation, generateOptions)
|
||||
|
||||
// Handle Icons as tehy need a preview
|
||||
console.log(columns[j].Code_Name)
|
||||
// Handle Icons as they need a preview
|
||||
if(columns[j].Code_Name == 'NEWDEV_dev_Icon')
|
||||
{
|
||||
input = `
|
||||
<span class="input-group-addon" id="txtIconFA"></span>
|
||||
<span class="input-group-addon iconPreview" my-customid="NEWDEV_dev_Icon_preview"></span>
|
||||
<select class="form-control"
|
||||
onChange="updateIconPreview('#NEWDEV_dev_Icon')"
|
||||
onChange="updateIconPreview(this)"
|
||||
my-customparams="NEWDEV_dev_Icon,NEWDEV_dev_Icon_preview"
|
||||
id="${columns[j].Code_Name}"
|
||||
data-my-column="${columns[j].Code_Name}"
|
||||
data-my-targetColumns="${columns[j].Code_Name.replace('NEWDEV_','')}" >
|
||||
@@ -163,7 +167,7 @@
|
||||
}
|
||||
|
||||
|
||||
} else if (elementsWithInputValue.elementType === 'input'){
|
||||
} else if (elementType === 'input'){
|
||||
|
||||
// Add classes specifically for checkboxes
|
||||
inputType === 'checkbox' ? inputClass = 'checkbox' : inputClass = 'form-control';
|
||||
@@ -171,6 +175,7 @@
|
||||
|
||||
input = `<input class="${inputClass}"
|
||||
id="${columns[j].Code_Name}"
|
||||
my-customid="${columns[j].Code_Name}"
|
||||
data-my-column="${columns[j].Code_Name}"
|
||||
data-my-targetColumns="${columns[j].Code_Name.replace('NEWDEV_','')}"
|
||||
type="${inputType}">`
|
||||
|
||||
@@ -783,7 +783,7 @@
|
||||
setCache(key, target.replaceAll(":","_")+'_id') // _id is added so it doesn't conflict with AdminLTE tab behavior
|
||||
}
|
||||
|
||||
// get the tab id from the cookie (already overriden by the target)
|
||||
// get the tab id from the cookie (already overridden by the target)
|
||||
if(!emptyArr.includes(getCache(key)))
|
||||
{
|
||||
selectedTab = getCache(key);
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<link rel="stylesheet" href="lib/AdminLTE/bower_components/select2/dist/css/select2.min.css">
|
||||
|
||||
<!-- NetAlertX -->
|
||||
<script src="js/handle_version.js"></script>
|
||||
<script defer src="js/handle_version.js"></script>
|
||||
<script src="js/ui_components.js?v=<?php include 'php/templates/version.php'; ?>"></script>
|
||||
|
||||
|
||||
|
||||
@@ -67,14 +67,16 @@ require dirname(__FILE__).'/security.php';
|
||||
<link id="favicon" 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">
|
||||
<link rel="manifest" href="img/manifest.json" crossorigin="use-credentials">
|
||||
<!-- Dark-Mode Patch -->
|
||||
<?php
|
||||
if ($ENABLED_DARKMODE === True) {
|
||||
echo '<link rel="stylesheet" href="css/dark-patch.css">';
|
||||
$BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/boxed-bg-dark.png\');"';
|
||||
} else { $BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/background.png\');"';}
|
||||
?>
|
||||
|
||||
<?php
|
||||
if ($ENABLED_DARKMODE === True) {
|
||||
echo '<link rel="stylesheet" href="css/dark-patch.css">';
|
||||
$BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/boxed-bg-dark.png\');"';
|
||||
} else { $BACKGROUND_IMAGE_PATCH='style="background-image: url(\'img/background.png\');"';}
|
||||
?>
|
||||
|
||||
|
||||
|
||||
<!-- Servertime to the right of the hostname -->
|
||||
@@ -312,9 +314,6 @@ if ($ENABLED_DARKMODE === True) {
|
||||
</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>
|
||||
|
||||
700
front/php/templates/language/cs_cz.json
Executable file
700
front/php/templates/language/cs_cz.json
Executable file
@@ -0,0 +1,700 @@
|
||||
{
|
||||
"API_CUSTOM_SQL_description": "",
|
||||
"API_CUSTOM_SQL_name": "",
|
||||
"API_display_name": "",
|
||||
"API_icon": "",
|
||||
"About_Design": "",
|
||||
"About_Exit": "",
|
||||
"About_Title": "",
|
||||
"AppEvents_DateTimeCreated": "",
|
||||
"AppEvents_Extra": "",
|
||||
"AppEvents_GUID": "",
|
||||
"AppEvents_Helper1": "",
|
||||
"AppEvents_Helper2": "",
|
||||
"AppEvents_Helper3": "",
|
||||
"AppEvents_ObjectForeignKey": "",
|
||||
"AppEvents_ObjectIndex": "",
|
||||
"AppEvents_ObjectIsArchived": "",
|
||||
"AppEvents_ObjectIsNew": "",
|
||||
"AppEvents_ObjectPlugin": "",
|
||||
"AppEvents_ObjectPrimaryID": "",
|
||||
"AppEvents_ObjectSecondaryID": "",
|
||||
"AppEvents_ObjectStatus": "",
|
||||
"AppEvents_ObjectStatusColumn": "",
|
||||
"AppEvents_ObjectType": "",
|
||||
"AppEvents_Plugin": "",
|
||||
"AppEvents_Type": "",
|
||||
"BackDevDetail_Actions_Ask_Run": "",
|
||||
"BackDevDetail_Actions_Not_Registered": "",
|
||||
"BackDevDetail_Actions_Title_Run": "",
|
||||
"BackDevDetail_Copy_Ask": "",
|
||||
"BackDevDetail_Copy_Title": "",
|
||||
"BackDevDetail_Tools_WOL_error": "",
|
||||
"BackDevDetail_Tools_WOL_okay": "",
|
||||
"BackDevices_Arpscan_disabled": "",
|
||||
"BackDevices_Arpscan_enabled": "",
|
||||
"BackDevices_Backup_CopError": "",
|
||||
"BackDevices_Backup_Failed": "",
|
||||
"BackDevices_Backup_okay": "",
|
||||
"BackDevices_DBTools_DelDevError_a": "",
|
||||
"BackDevices_DBTools_DelDevError_b": "",
|
||||
"BackDevices_DBTools_DelDev_a": "",
|
||||
"BackDevices_DBTools_DelDev_b": "",
|
||||
"BackDevices_DBTools_DelEvents": "",
|
||||
"BackDevices_DBTools_DelEventsError": "",
|
||||
"BackDevices_DBTools_ImportCSV": "",
|
||||
"BackDevices_DBTools_ImportCSVError": "",
|
||||
"BackDevices_DBTools_ImportCSVMissing": "",
|
||||
"BackDevices_DBTools_Purge": "",
|
||||
"BackDevices_DBTools_UpdDev": "",
|
||||
"BackDevices_DBTools_UpdDevError": "",
|
||||
"BackDevices_DBTools_Upgrade": "",
|
||||
"BackDevices_DBTools_UpgradeError": "",
|
||||
"BackDevices_Device_UpdDevError": "",
|
||||
"BackDevices_Restore_CopError": "",
|
||||
"BackDevices_Restore_Failed": "",
|
||||
"BackDevices_Restore_okay": "",
|
||||
"BackDevices_darkmode_disabled": "",
|
||||
"BackDevices_darkmode_enabled": "",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "",
|
||||
"DevDetail_Copy_Device_Title": "",
|
||||
"DevDetail_Copy_Device_Tooltip": "",
|
||||
"DevDetail_EveandAl_AlertAllEvents": "",
|
||||
"DevDetail_EveandAl_AlertDown": "",
|
||||
"DevDetail_EveandAl_Archived": "",
|
||||
"DevDetail_EveandAl_NewDevice": "",
|
||||
"DevDetail_EveandAl_NewDevice_Tooltip": "",
|
||||
"DevDetail_EveandAl_RandomMAC": "",
|
||||
"DevDetail_EveandAl_ScanCycle": "",
|
||||
"DevDetail_EveandAl_ScanCycle_a": "",
|
||||
"DevDetail_EveandAl_ScanCycle_z": "",
|
||||
"DevDetail_EveandAl_Skip": "",
|
||||
"DevDetail_EveandAl_Title": "",
|
||||
"DevDetail_Events_CheckBox": "",
|
||||
"DevDetail_GoToNetworkNode": "",
|
||||
"DevDetail_Icon": "",
|
||||
"DevDetail_Icon_Descr": "",
|
||||
"DevDetail_Loading": "",
|
||||
"DevDetail_MainInfo_Comments": "",
|
||||
"DevDetail_MainInfo_Favorite": "",
|
||||
"DevDetail_MainInfo_Group": "",
|
||||
"DevDetail_MainInfo_Location": "",
|
||||
"DevDetail_MainInfo_Name": "",
|
||||
"DevDetail_MainInfo_Network": "",
|
||||
"DevDetail_MainInfo_Network_Port": "",
|
||||
"DevDetail_MainInfo_Network_Site": "",
|
||||
"DevDetail_MainInfo_Network_Title": "",
|
||||
"DevDetail_MainInfo_Owner": "",
|
||||
"DevDetail_MainInfo_SSID": "",
|
||||
"DevDetail_MainInfo_Title": "",
|
||||
"DevDetail_MainInfo_Type": "",
|
||||
"DevDetail_MainInfo_Vendor": "",
|
||||
"DevDetail_MainInfo_mac": "",
|
||||
"DevDetail_Network_Node_hover": "",
|
||||
"DevDetail_Network_Port_hover": "",
|
||||
"DevDetail_Nmap_Scans": "",
|
||||
"DevDetail_Nmap_Scans_desc": "",
|
||||
"DevDetail_Nmap_buttonDefault": "",
|
||||
"DevDetail_Nmap_buttonDefault_text": "",
|
||||
"DevDetail_Nmap_buttonDetail": "",
|
||||
"DevDetail_Nmap_buttonDetail_text": "",
|
||||
"DevDetail_Nmap_buttonFast": "",
|
||||
"DevDetail_Nmap_buttonFast_text": "",
|
||||
"DevDetail_Nmap_buttonSkipDiscovery": "",
|
||||
"DevDetail_Nmap_buttonSkipDiscovery_text": "",
|
||||
"DevDetail_Nmap_resultsLink": "",
|
||||
"DevDetail_Owner_hover": "",
|
||||
"DevDetail_Periodselect_All": "",
|
||||
"DevDetail_Periodselect_LastMonth": "",
|
||||
"DevDetail_Periodselect_LastWeek": "",
|
||||
"DevDetail_Periodselect_LastYear": "",
|
||||
"DevDetail_Periodselect_today": "",
|
||||
"DevDetail_Run_Actions_Title": "",
|
||||
"DevDetail_Run_Actions_Tooltip": "",
|
||||
"DevDetail_SessionInfo_FirstSession": "",
|
||||
"DevDetail_SessionInfo_LastIP": "",
|
||||
"DevDetail_SessionInfo_LastSession": "",
|
||||
"DevDetail_SessionInfo_StaticIP": "",
|
||||
"DevDetail_SessionInfo_Status": "",
|
||||
"DevDetail_SessionInfo_Title": "",
|
||||
"DevDetail_SessionTable_Additionalinfo": "",
|
||||
"DevDetail_SessionTable_Connection": "",
|
||||
"DevDetail_SessionTable_Disconnection": "",
|
||||
"DevDetail_SessionTable_Duration": "",
|
||||
"DevDetail_SessionTable_IP": "",
|
||||
"DevDetail_SessionTable_Order": "",
|
||||
"DevDetail_Shortcut_CurrentStatus": "",
|
||||
"DevDetail_Shortcut_DownAlerts": "",
|
||||
"DevDetail_Shortcut_Presence": "",
|
||||
"DevDetail_Shortcut_Sessions": "",
|
||||
"DevDetail_Tab_Details": "",
|
||||
"DevDetail_Tab_Events": "",
|
||||
"DevDetail_Tab_EventsTableDate": "",
|
||||
"DevDetail_Tab_EventsTableEvent": "",
|
||||
"DevDetail_Tab_EventsTableIP": "",
|
||||
"DevDetail_Tab_EventsTableInfo": "",
|
||||
"DevDetail_Tab_Nmap": "",
|
||||
"DevDetail_Tab_NmapEmpty": "",
|
||||
"DevDetail_Tab_NmapTableExtra": "",
|
||||
"DevDetail_Tab_NmapTableHeader": "",
|
||||
"DevDetail_Tab_NmapTableIndex": "",
|
||||
"DevDetail_Tab_NmapTablePort": "",
|
||||
"DevDetail_Tab_NmapTableService": "",
|
||||
"DevDetail_Tab_NmapTableState": "",
|
||||
"DevDetail_Tab_NmapTableText": "",
|
||||
"DevDetail_Tab_NmapTableTime": "",
|
||||
"DevDetail_Tab_Plugins": "",
|
||||
"DevDetail_Tab_Presence": "",
|
||||
"DevDetail_Tab_Sessions": "",
|
||||
"DevDetail_Tab_Tools": "",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Description": "",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Error": "",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Start": "",
|
||||
"DevDetail_Tab_Tools_Internet_Info_Title": "",
|
||||
"DevDetail_Tab_Tools_Nslookup_Description": "",
|
||||
"DevDetail_Tab_Tools_Nslookup_Error": "",
|
||||
"DevDetail_Tab_Tools_Nslookup_Start": "",
|
||||
"DevDetail_Tab_Tools_Nslookup_Title": "",
|
||||
"DevDetail_Tab_Tools_Speedtest_Description": "",
|
||||
"DevDetail_Tab_Tools_Speedtest_Start": "",
|
||||
"DevDetail_Tab_Tools_Speedtest_Title": "",
|
||||
"DevDetail_Tab_Tools_Traceroute_Description": "",
|
||||
"DevDetail_Tab_Tools_Traceroute_Error": "",
|
||||
"DevDetail_Tab_Tools_Traceroute_Start": "",
|
||||
"DevDetail_Tab_Tools_Traceroute_Title": "",
|
||||
"DevDetail_Tools_WOL": "",
|
||||
"DevDetail_Tools_WOL_noti": "",
|
||||
"DevDetail_Tools_WOL_noti_text": "",
|
||||
"DevDetail_Type_hover": "",
|
||||
"DevDetail_Vendor_hover": "",
|
||||
"DevDetail_WOL_Title": "",
|
||||
"DevDetail_button_AddIcon": "",
|
||||
"DevDetail_button_AddIcon_Help": "",
|
||||
"DevDetail_button_AddIcon_Tooltip": "",
|
||||
"DevDetail_button_Delete": "",
|
||||
"DevDetail_button_DeleteEvents": "",
|
||||
"DevDetail_button_DeleteEvents_Warning": "",
|
||||
"DevDetail_button_OverwriteIcons": "",
|
||||
"DevDetail_button_OverwriteIcons_Tooltip": "",
|
||||
"DevDetail_button_OverwriteIcons_Warning": "",
|
||||
"DevDetail_button_Reset": "",
|
||||
"DevDetail_button_Save": "",
|
||||
"Device_MultiEdit": "",
|
||||
"Device_MultiEdit_Backup": "",
|
||||
"Device_MultiEdit_Fields": "",
|
||||
"Device_MultiEdit_MassActions": "",
|
||||
"Device_MultiEdit_Tooltip": "",
|
||||
"Device_Searchbox": "",
|
||||
"Device_Shortcut_AllDevices": "",
|
||||
"Device_Shortcut_Archived": "",
|
||||
"Device_Shortcut_Connected": "",
|
||||
"Device_Shortcut_Devices": "",
|
||||
"Device_Shortcut_DownAlerts": "",
|
||||
"Device_Shortcut_DownOnly": "",
|
||||
"Device_Shortcut_Favorites": "",
|
||||
"Device_Shortcut_NewDevices": "",
|
||||
"Device_Shortcut_OnlineChart": "",
|
||||
"Device_TableHead_Connected_Devices": "",
|
||||
"Device_TableHead_Favorite": "",
|
||||
"Device_TableHead_FirstSession": "",
|
||||
"Device_TableHead_GUID": "",
|
||||
"Device_TableHead_Group": "",
|
||||
"Device_TableHead_Icon": "",
|
||||
"Device_TableHead_LastIP": "",
|
||||
"Device_TableHead_LastIPOrder": "",
|
||||
"Device_TableHead_LastSession": "",
|
||||
"Device_TableHead_Location": "",
|
||||
"Device_TableHead_MAC": "",
|
||||
"Device_TableHead_MAC_full": "",
|
||||
"Device_TableHead_Name": "",
|
||||
"Device_TableHead_NetworkSite": "",
|
||||
"Device_TableHead_Owner": "",
|
||||
"Device_TableHead_Parent_MAC": "",
|
||||
"Device_TableHead_Port": "",
|
||||
"Device_TableHead_RowID": "",
|
||||
"Device_TableHead_Rowid": "",
|
||||
"Device_TableHead_SSID": "",
|
||||
"Device_TableHead_Status": "",
|
||||
"Device_TableHead_SyncHubNodeName": "",
|
||||
"Device_TableHead_Type": "",
|
||||
"Device_TableHead_Vendor": "",
|
||||
"Device_Table_Not_Network_Device": "",
|
||||
"Device_Table_info": "",
|
||||
"Device_Table_nav_next": "",
|
||||
"Device_Table_nav_prev": "",
|
||||
"Device_Tablelenght": "",
|
||||
"Device_Tablelenght_all": "",
|
||||
"Device_Title": "",
|
||||
"Donations_Others": "",
|
||||
"Donations_Platforms": "",
|
||||
"Donations_Text": "",
|
||||
"Donations_Title": "",
|
||||
"ENABLE_PLUGINS_description": "",
|
||||
"ENABLE_PLUGINS_name": "",
|
||||
"Email_display_name": "",
|
||||
"Email_icon": "",
|
||||
"Events_Loading": "",
|
||||
"Events_Periodselect_All": "",
|
||||
"Events_Periodselect_LastMonth": "",
|
||||
"Events_Periodselect_LastWeek": "",
|
||||
"Events_Periodselect_LastYear": "",
|
||||
"Events_Periodselect_today": "",
|
||||
"Events_Searchbox": "",
|
||||
"Events_Shortcut_AllEvents": "",
|
||||
"Events_Shortcut_DownAlerts": "",
|
||||
"Events_Shortcut_Events": "",
|
||||
"Events_Shortcut_MissSessions": "",
|
||||
"Events_Shortcut_NewDevices": "",
|
||||
"Events_Shortcut_Sessions": "",
|
||||
"Events_Shortcut_VoidSessions": "",
|
||||
"Events_TableHead_AdditionalInfo": "",
|
||||
"Events_TableHead_Connection": "",
|
||||
"Events_TableHead_Date": "",
|
||||
"Events_TableHead_Device": "",
|
||||
"Events_TableHead_Disconnection": "",
|
||||
"Events_TableHead_Duration": "",
|
||||
"Events_TableHead_DurationOrder": "",
|
||||
"Events_TableHead_EventType": "",
|
||||
"Events_TableHead_IP": "",
|
||||
"Events_TableHead_IPOrder": "",
|
||||
"Events_TableHead_Order": "",
|
||||
"Events_TableHead_Owner": "",
|
||||
"Events_TableHead_PendingAlert": "",
|
||||
"Events_Table_info": "",
|
||||
"Events_Table_nav_next": "",
|
||||
"Events_Table_nav_prev": "",
|
||||
"Events_Tablelenght": "",
|
||||
"Events_Tablelenght_all": "",
|
||||
"Events_Title": "",
|
||||
"Gen_Action": "",
|
||||
"Gen_Add": "",
|
||||
"Gen_Add_All": "",
|
||||
"Gen_All_Devices": "",
|
||||
"Gen_AreYouSure": "",
|
||||
"Gen_Backup": "",
|
||||
"Gen_Cancel": "",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "",
|
||||
"Gen_DataUpdatedUITakesTime": "",
|
||||
"Gen_Delete": "",
|
||||
"Gen_DeleteAll": "",
|
||||
"Gen_Error": "",
|
||||
"Gen_Filter": "",
|
||||
"Gen_LockedDB": "",
|
||||
"Gen_Offline": "",
|
||||
"Gen_Okay": "",
|
||||
"Gen_Purge": "",
|
||||
"Gen_ReadDocs": "",
|
||||
"Gen_Remove_All": "",
|
||||
"Gen_Remove_Last": "",
|
||||
"Gen_Restore": "",
|
||||
"Gen_Run": "",
|
||||
"Gen_Save": "",
|
||||
"Gen_Saved": "",
|
||||
"Gen_Search": "",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "",
|
||||
"Gen_Switch": "",
|
||||
"Gen_Upd": "",
|
||||
"Gen_Upd_Fail": "",
|
||||
"Gen_Update": "",
|
||||
"Gen_Update_Value": "",
|
||||
"Gen_Warning": "",
|
||||
"Gen_Work_In_Progress": "",
|
||||
"General_display_name": "",
|
||||
"General_icon": "",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "",
|
||||
"HelpFAQ_Cat_Detail": "",
|
||||
"HelpFAQ_Cat_Detail_300_head": "",
|
||||
"HelpFAQ_Cat_Detail_300_text_a": "",
|
||||
"HelpFAQ_Cat_Detail_300_text_b": "",
|
||||
"HelpFAQ_Cat_Detail_301_head_a": "",
|
||||
"HelpFAQ_Cat_Detail_301_head_b": "",
|
||||
"HelpFAQ_Cat_Detail_301_text": "",
|
||||
"HelpFAQ_Cat_Detail_302_head_a": "",
|
||||
"HelpFAQ_Cat_Detail_302_head_b": "",
|
||||
"HelpFAQ_Cat_Detail_302_text": "",
|
||||
"HelpFAQ_Cat_Detail_303_head": "",
|
||||
"HelpFAQ_Cat_Detail_303_text": "",
|
||||
"HelpFAQ_Cat_Device_200_head": "",
|
||||
"HelpFAQ_Cat_Device_200_text": "",
|
||||
"HelpFAQ_Cat_General": "",
|
||||
"HelpFAQ_Cat_General_100_head": "",
|
||||
"HelpFAQ_Cat_General_100_text_a": "",
|
||||
"HelpFAQ_Cat_General_100_text_b": "",
|
||||
"HelpFAQ_Cat_General_100_text_c": "",
|
||||
"HelpFAQ_Cat_General_101_head": "",
|
||||
"HelpFAQ_Cat_General_101_text": "",
|
||||
"HelpFAQ_Cat_General_102_head": "",
|
||||
"HelpFAQ_Cat_General_102_text": "",
|
||||
"HelpFAQ_Cat_General_102docker_head": "",
|
||||
"HelpFAQ_Cat_General_102docker_text": "",
|
||||
"HelpFAQ_Cat_General_103_head": "",
|
||||
"HelpFAQ_Cat_General_103_text": "",
|
||||
"HelpFAQ_Cat_Network_600_head": "",
|
||||
"HelpFAQ_Cat_Network_600_text": "",
|
||||
"HelpFAQ_Cat_Network_601_head": "",
|
||||
"HelpFAQ_Cat_Network_601_text": "",
|
||||
"HelpFAQ_Cat_Presence_400_head": "",
|
||||
"HelpFAQ_Cat_Presence_400_text": "",
|
||||
"HelpFAQ_Cat_Presence_401_head": "",
|
||||
"HelpFAQ_Cat_Presence_401_text": "",
|
||||
"HelpFAQ_Title": "",
|
||||
"LOADED_PLUGINS_description": "",
|
||||
"LOADED_PLUGINS_name": "",
|
||||
"LOG_LEVEL_description": "",
|
||||
"LOG_LEVEL_name": "",
|
||||
"Loading": "",
|
||||
"Login_Box": "",
|
||||
"Login_Default_PWD": "",
|
||||
"Login_Psw-box": "",
|
||||
"Login_Psw_alert": "",
|
||||
"Login_Psw_folder": "",
|
||||
"Login_Psw_new": "",
|
||||
"Login_Psw_run": "",
|
||||
"Login_Remember": "",
|
||||
"Login_Remember_small": "",
|
||||
"Login_Submit": "",
|
||||
"Login_Toggle_Alert_headline": "",
|
||||
"Login_Toggle_Info": "",
|
||||
"Login_Toggle_Info_headline": "",
|
||||
"Maint_PurgeLog": "",
|
||||
"Maint_RestartServer": "",
|
||||
"Maint_Restart_Server_noti_text": "",
|
||||
"Maintenance_Running_Version": "",
|
||||
"Maintenance_Status": "",
|
||||
"Maintenance_Title": "",
|
||||
"Maintenance_Tool_ExportCSV": "",
|
||||
"Maintenance_Tool_ExportCSV_noti": "",
|
||||
"Maintenance_Tool_ExportCSV_noti_text": "",
|
||||
"Maintenance_Tool_ExportCSV_text": "",
|
||||
"Maintenance_Tool_ImportCSV": "",
|
||||
"Maintenance_Tool_ImportCSV_noti": "",
|
||||
"Maintenance_Tool_ImportCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportCSV_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
|
||||
"Maintenance_Tool_ImportPastedCSV_text": "",
|
||||
"Maintenance_Tool_arpscansw": "",
|
||||
"Maintenance_Tool_arpscansw_noti": "",
|
||||
"Maintenance_Tool_arpscansw_noti_text": "",
|
||||
"Maintenance_Tool_arpscansw_text": "",
|
||||
"Maintenance_Tool_backup": "",
|
||||
"Maintenance_Tool_backup_noti": "",
|
||||
"Maintenance_Tool_backup_noti_text": "",
|
||||
"Maintenance_Tool_backup_text": "",
|
||||
"Maintenance_Tool_check_visible": "",
|
||||
"Maintenance_Tool_darkmode": "",
|
||||
"Maintenance_Tool_darkmode_noti": "",
|
||||
"Maintenance_Tool_darkmode_noti_text": "",
|
||||
"Maintenance_Tool_darkmode_text": "",
|
||||
"Maintenance_Tool_del_ActHistory": "",
|
||||
"Maintenance_Tool_del_ActHistory_noti": "",
|
||||
"Maintenance_Tool_del_ActHistory_noti_text": "",
|
||||
"Maintenance_Tool_del_ActHistory_text": "",
|
||||
"Maintenance_Tool_del_alldev": "",
|
||||
"Maintenance_Tool_del_alldev_noti": "",
|
||||
"Maintenance_Tool_del_alldev_noti_text": "",
|
||||
"Maintenance_Tool_del_alldev_text": "",
|
||||
"Maintenance_Tool_del_allevents": "",
|
||||
"Maintenance_Tool_del_allevents30": "",
|
||||
"Maintenance_Tool_del_allevents30_noti": "",
|
||||
"Maintenance_Tool_del_allevents30_noti_text": "",
|
||||
"Maintenance_Tool_del_allevents30_text": "",
|
||||
"Maintenance_Tool_del_allevents_noti": "",
|
||||
"Maintenance_Tool_del_allevents_noti_text": "",
|
||||
"Maintenance_Tool_del_allevents_text": "",
|
||||
"Maintenance_Tool_del_empty_macs": "",
|
||||
"Maintenance_Tool_del_empty_macs_noti": "",
|
||||
"Maintenance_Tool_del_empty_macs_noti_text": "",
|
||||
"Maintenance_Tool_del_empty_macs_text": "",
|
||||
"Maintenance_Tool_del_selecteddev": "",
|
||||
"Maintenance_Tool_del_selecteddev_text": "",
|
||||
"Maintenance_Tool_del_unknowndev": "",
|
||||
"Maintenance_Tool_del_unknowndev_noti": "",
|
||||
"Maintenance_Tool_del_unknowndev_noti_text": "",
|
||||
"Maintenance_Tool_del_unknowndev_text": "",
|
||||
"Maintenance_Tool_displayed_columns_text": "",
|
||||
"Maintenance_Tool_drag_me": "",
|
||||
"Maintenance_Tool_order_columns_text": "",
|
||||
"Maintenance_Tool_purgebackup": "",
|
||||
"Maintenance_Tool_purgebackup_noti": "",
|
||||
"Maintenance_Tool_purgebackup_noti_text": "",
|
||||
"Maintenance_Tool_purgebackup_text": "",
|
||||
"Maintenance_Tool_restore": "",
|
||||
"Maintenance_Tool_restore_noti": "",
|
||||
"Maintenance_Tool_restore_noti_text": "",
|
||||
"Maintenance_Tool_restore_text": "",
|
||||
"Maintenance_Tool_upgrade_database_noti": "",
|
||||
"Maintenance_Tool_upgrade_database_noti_text": "",
|
||||
"Maintenance_Tool_upgrade_database_text": "",
|
||||
"Maintenance_Tools_Tab_BackupRestore": "",
|
||||
"Maintenance_Tools_Tab_Logging": "",
|
||||
"Maintenance_Tools_Tab_Settings": "",
|
||||
"Maintenance_Tools_Tab_Tools": "",
|
||||
"Maintenance_Tools_Tab_UISettings": "",
|
||||
"Maintenance_arp_status": "",
|
||||
"Maintenance_arp_status_off": "",
|
||||
"Maintenance_arp_status_on": "",
|
||||
"Maintenance_built_on": "",
|
||||
"Maintenance_current_version": "",
|
||||
"Maintenance_database_backup": "",
|
||||
"Maintenance_database_backup_found": "",
|
||||
"Maintenance_database_backup_total": "",
|
||||
"Maintenance_database_lastmod": "",
|
||||
"Maintenance_database_path": "",
|
||||
"Maintenance_database_rows": "",
|
||||
"Maintenance_database_size": "",
|
||||
"Maintenance_lang_selector_apply": "",
|
||||
"Maintenance_lang_selector_empty": "",
|
||||
"Maintenance_lang_selector_lable": "",
|
||||
"Maintenance_lang_selector_text": "",
|
||||
"Maintenance_new_version": "",
|
||||
"Maintenance_themeselector_apply": "",
|
||||
"Maintenance_themeselector_empty": "",
|
||||
"Maintenance_themeselector_lable": "",
|
||||
"Maintenance_themeselector_text": "",
|
||||
"Maintenance_version": "",
|
||||
"NETWORK_DEVICE_TYPES_description": "",
|
||||
"NETWORK_DEVICE_TYPES_name": "",
|
||||
"Navigation_About": "",
|
||||
"Navigation_Devices": "",
|
||||
"Navigation_Donations": "",
|
||||
"Navigation_Events": "",
|
||||
"Navigation_HelpFAQ": "",
|
||||
"Navigation_Integrations": "",
|
||||
"Navigation_Maintenance": "",
|
||||
"Navigation_Monitoring": "",
|
||||
"Navigation_Network": "",
|
||||
"Navigation_Notifications": "",
|
||||
"Navigation_Plugins": "",
|
||||
"Navigation_Presence": "",
|
||||
"Navigation_Report": "",
|
||||
"Navigation_Settings": "",
|
||||
"Navigation_SystemInfo": "",
|
||||
"Navigation_Workflows": "",
|
||||
"Network_Assign": "",
|
||||
"Network_Cant_Assign": "",
|
||||
"Network_Configuration_Error": "",
|
||||
"Network_Connected": "",
|
||||
"Network_ManageAdd": "",
|
||||
"Network_ManageAdd_Name": "",
|
||||
"Network_ManageAdd_Name_text": "",
|
||||
"Network_ManageAdd_Port": "",
|
||||
"Network_ManageAdd_Port_text": "",
|
||||
"Network_ManageAdd_Submit": "",
|
||||
"Network_ManageAdd_Type": "",
|
||||
"Network_ManageAdd_Type_text": "",
|
||||
"Network_ManageAssign": "",
|
||||
"Network_ManageDel": "",
|
||||
"Network_ManageDel_Name": "",
|
||||
"Network_ManageDel_Name_text": "",
|
||||
"Network_ManageDel_Submit": "",
|
||||
"Network_ManageDevices": "",
|
||||
"Network_ManageEdit": "",
|
||||
"Network_ManageEdit_ID": "",
|
||||
"Network_ManageEdit_ID_text": "",
|
||||
"Network_ManageEdit_Name": "",
|
||||
"Network_ManageEdit_Name_text": "",
|
||||
"Network_ManageEdit_Port": "",
|
||||
"Network_ManageEdit_Port_text": "",
|
||||
"Network_ManageEdit_Submit": "",
|
||||
"Network_ManageEdit_Type": "",
|
||||
"Network_ManageEdit_Type_text": "",
|
||||
"Network_ManageLeaf": "",
|
||||
"Network_ManageUnassign": "",
|
||||
"Network_NoAssignedDevices": "",
|
||||
"Network_NoDevices": "",
|
||||
"Network_Node": "",
|
||||
"Network_Node_Name": "",
|
||||
"Network_Parent": "",
|
||||
"Network_Root": "",
|
||||
"Network_Root_Not_Configured": "",
|
||||
"Network_Root_Unconfigurable": "",
|
||||
"Network_Table_Hostname": "",
|
||||
"Network_Table_IP": "",
|
||||
"Network_Table_State": "",
|
||||
"Network_Title": "",
|
||||
"Network_UnassignedDevices": "",
|
||||
"Notifications_All": "",
|
||||
"Notifications_Mark_All_Read": "",
|
||||
"PIALERT_WEB_PASSWORD_description": "",
|
||||
"PIALERT_WEB_PASSWORD_name": "",
|
||||
"PIALERT_WEB_PROTECTION_description": "",
|
||||
"PIALERT_WEB_PROTECTION_name": "",
|
||||
"PLUGINS_KEEP_HIST_description": "",
|
||||
"PLUGINS_KEEP_HIST_name": "",
|
||||
"Plugins_DeleteAll": "",
|
||||
"Plugins_Filters_Mac": "",
|
||||
"Plugins_History": "",
|
||||
"Plugins_Objects": "",
|
||||
"Plugins_Out_of": "",
|
||||
"Plugins_Unprocessed_Events": "",
|
||||
"Plugins_no_control": "",
|
||||
"Presence_CalHead_day": "",
|
||||
"Presence_CalHead_lang": "",
|
||||
"Presence_CalHead_month": "",
|
||||
"Presence_CalHead_quarter": "",
|
||||
"Presence_CalHead_week": "",
|
||||
"Presence_CalHead_year": "",
|
||||
"Presence_CallHead_Devices": "",
|
||||
"Presence_Loading": "",
|
||||
"Presence_Shortcut_AllDevices": "",
|
||||
"Presence_Shortcut_Archived": "",
|
||||
"Presence_Shortcut_Connected": "",
|
||||
"Presence_Shortcut_Devices": "",
|
||||
"Presence_Shortcut_DownAlerts": "",
|
||||
"Presence_Shortcut_Favorites": "",
|
||||
"Presence_Shortcut_NewDevices": "",
|
||||
"Presence_Title": "",
|
||||
"REPORT_DASHBOARD_URL_description": "",
|
||||
"REPORT_DASHBOARD_URL_name": "",
|
||||
"REPORT_ERROR": "",
|
||||
"REPORT_MAIL_description": "",
|
||||
"REPORT_MAIL_name": "",
|
||||
"REPORT_TITLE": "",
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
"Settings_Metadata_Toggle": "",
|
||||
"Settings_device_Scanners_desync": "",
|
||||
"Settings_device_Scanners_desync_popup": "",
|
||||
"Speedtest_Results": "",
|
||||
"Systeminfo_CPU": "",
|
||||
"Systeminfo_CPU_Cores": "",
|
||||
"Systeminfo_CPU_Name": "",
|
||||
"Systeminfo_CPU_Speed": "",
|
||||
"Systeminfo_CPU_Temp": "",
|
||||
"Systeminfo_CPU_Vendor": "",
|
||||
"Systeminfo_Client_Resolution": "",
|
||||
"Systeminfo_Client_User_Agent": "",
|
||||
"Systeminfo_General": "",
|
||||
"Systeminfo_General_Date": "",
|
||||
"Systeminfo_General_Date2": "",
|
||||
"Systeminfo_General_Full_Date": "",
|
||||
"Systeminfo_General_TimeZone": "",
|
||||
"Systeminfo_Memory": "",
|
||||
"Systeminfo_Memory_Total_Memory": "",
|
||||
"Systeminfo_Memory_Usage": "",
|
||||
"Systeminfo_Memory_Usage_Percent": "",
|
||||
"Systeminfo_Motherboard": "",
|
||||
"Systeminfo_Motherboard_BIOS": "",
|
||||
"Systeminfo_Motherboard_BIOS_Date": "",
|
||||
"Systeminfo_Motherboard_BIOS_Vendor": "",
|
||||
"Systeminfo_Motherboard_Manufactured": "",
|
||||
"Systeminfo_Motherboard_Name": "",
|
||||
"Systeminfo_Motherboard_Revision": "",
|
||||
"Systeminfo_Network": "",
|
||||
"Systeminfo_Network_Accept_Encoding": "",
|
||||
"Systeminfo_Network_Accept_Language": "",
|
||||
"Systeminfo_Network_Connection_Port": "",
|
||||
"Systeminfo_Network_HTTP_Host": "",
|
||||
"Systeminfo_Network_HTTP_Referer": "",
|
||||
"Systeminfo_Network_HTTP_Referer_String": "",
|
||||
"Systeminfo_Network_Hardware": "",
|
||||
"Systeminfo_Network_Hardware_Interface_Mask": "",
|
||||
"Systeminfo_Network_Hardware_Interface_Name": "",
|
||||
"Systeminfo_Network_Hardware_Interface_RX": "",
|
||||
"Systeminfo_Network_Hardware_Interface_TX": "",
|
||||
"Systeminfo_Network_IP": "",
|
||||
"Systeminfo_Network_IP_Connection": "",
|
||||
"Systeminfo_Network_IP_Server": "",
|
||||
"Systeminfo_Network_MIME": "",
|
||||
"Systeminfo_Network_Request_Method": "",
|
||||
"Systeminfo_Network_Request_Time": "",
|
||||
"Systeminfo_Network_Request_URI": "",
|
||||
"Systeminfo_Network_Secure_Connection": "",
|
||||
"Systeminfo_Network_Secure_Connection_String": "",
|
||||
"Systeminfo_Network_Server_Name": "",
|
||||
"Systeminfo_Network_Server_Name_String": "",
|
||||
"Systeminfo_Network_Server_Query": "",
|
||||
"Systeminfo_Network_Server_Query_String": "",
|
||||
"Systeminfo_Network_Server_Version": "",
|
||||
"Systeminfo_Services": "",
|
||||
"Systeminfo_Services_Description": "",
|
||||
"Systeminfo_Services_Name": "",
|
||||
"Systeminfo_Storage": "",
|
||||
"Systeminfo_Storage_Device": "",
|
||||
"Systeminfo_Storage_Mount": "",
|
||||
"Systeminfo_Storage_Size": "",
|
||||
"Systeminfo_Storage_Type": "",
|
||||
"Systeminfo_Storage_Usage": "",
|
||||
"Systeminfo_Storage_Usage_Free": "",
|
||||
"Systeminfo_Storage_Usage_Mount": "",
|
||||
"Systeminfo_Storage_Usage_Total": "",
|
||||
"Systeminfo_Storage_Usage_Used": "",
|
||||
"Systeminfo_System": "",
|
||||
"Systeminfo_System_AVG": "",
|
||||
"Systeminfo_System_Architecture": "",
|
||||
"Systeminfo_System_Kernel": "",
|
||||
"Systeminfo_System_OSVersion": "",
|
||||
"Systeminfo_System_Running_Processes": "",
|
||||
"Systeminfo_System_System": "",
|
||||
"Systeminfo_System_Uname": "",
|
||||
"Systeminfo_System_Uptime": "",
|
||||
"Systeminfo_This_Client": "",
|
||||
"Systeminfo_USB_Devices": "",
|
||||
"TICKER_MIGRATE_TO_NETALERTX": "",
|
||||
"TIMEZONE_description": "",
|
||||
"TIMEZONE_name": "",
|
||||
"UI_DEV_SECTIONS_description": "",
|
||||
"UI_DEV_SECTIONS_name": "",
|
||||
"UI_ICONS_description": "",
|
||||
"UI_ICONS_name": "",
|
||||
"UI_LANG_description": "",
|
||||
"UI_LANG_name": "",
|
||||
"UI_MY_DEVICES_description": "",
|
||||
"UI_MY_DEVICES_name": "",
|
||||
"UI_NOT_RANDOM_MAC_description": "",
|
||||
"UI_NOT_RANDOM_MAC_name": "",
|
||||
"UI_PRESENCE_description": "",
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
"report_guid": "",
|
||||
"report_guid_missing": "",
|
||||
"report_select_format": "",
|
||||
"report_time": "",
|
||||
"run_event_icon": "",
|
||||
"run_event_tooltip": "",
|
||||
"settings_core_icon": "",
|
||||
"settings_core_label": "",
|
||||
"settings_device_scanners": "",
|
||||
"settings_device_scanners_icon": "",
|
||||
"settings_device_scanners_info": "",
|
||||
"settings_device_scanners_label": "",
|
||||
"settings_enabled": "",
|
||||
"settings_enabled_icon": "",
|
||||
"settings_expand_all": "",
|
||||
"settings_imported": "",
|
||||
"settings_imported_label": "",
|
||||
"settings_missing": "",
|
||||
"settings_missing_block": "",
|
||||
"settings_old": "",
|
||||
"settings_other_scanners": "",
|
||||
"settings_other_scanners_icon": "",
|
||||
"settings_other_scanners_label": "",
|
||||
"settings_publishers": "",
|
||||
"settings_publishers_icon": "",
|
||||
"settings_publishers_info": "",
|
||||
"settings_publishers_label": "",
|
||||
"settings_saved": "",
|
||||
"settings_system_icon": "",
|
||||
"settings_system_label": "",
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_icon": "",
|
||||
"test_event_tooltip": ""
|
||||
}
|
||||
7
front/php/templates/language/de_de.json
Normal file → Executable file
7
front/php/templates/language/de_de.json
Normal file → Executable file
@@ -68,6 +68,8 @@
|
||||
"BackDevices_Restore_okay": "Die Wiederherstellung wurde erfolgreich ausgeführt.",
|
||||
"BackDevices_darkmode_disabled": "Heller Modus aktiviert.",
|
||||
"BackDevices_darkmode_enabled": "Dunkler Modus aktiviert.",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"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",
|
||||
@@ -286,6 +288,7 @@
|
||||
"Gen_AreYouSure": "Sind Sie sich sicher?",
|
||||
"Gen_Backup": "Sichern",
|
||||
"Gen_Cancel": "Abbrechen",
|
||||
"Gen_Change": "",
|
||||
"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",
|
||||
@@ -304,6 +307,7 @@
|
||||
"Gen_Save": "Speichern",
|
||||
"Gen_Saved": "Gespeichert",
|
||||
"Gen_Search": "Suchen",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Ausgewählte Geräte:",
|
||||
"Gen_Switch": "Umschalten",
|
||||
"Gen_Upd": "Aktualisierung erfolgreich",
|
||||
@@ -611,6 +615,7 @@
|
||||
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.",
|
||||
"Reports_Sent_Log": "Protokoll gesendeter Berichte",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"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. ",
|
||||
@@ -723,6 +728,8 @@
|
||||
"UI_PRESENCE_name": "Anzeige im Präsenzdiagramm",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "Automatisch Aktualisieren",
|
||||
"VERSION_description": "",
|
||||
"VERSION_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.",
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Restore executed successfully.",
|
||||
"BackDevices_darkmode_disabled": "Darkmode Disabled",
|
||||
"BackDevices_darkmode_enabled": "Darkmode Enabled",
|
||||
"CLEAR_NEW_FLAG_description": "If enabled (<code>0</code> is disabled), devices flagged as <b>New Device</b> will be unflagged if the time limit (specified in hours) exceeds their <b>First Session</b> time.",
|
||||
"CLEAR_NEW_FLAG_name": "Clear new flag",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "This is a maintenance setting. This specifies the number of days worth of event entries that will be kept. All older events will be deleted periodically. Also applies on Plugin Events History.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Delete events older than",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copy details from device",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Are you sure?",
|
||||
"Gen_Backup": "Run Backup",
|
||||
"Gen_Cancel": "Cancel",
|
||||
"Gen_Change": "Change",
|
||||
"Gen_Copy": "Run",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - It may take a while for the UI to update if a scan is running.",
|
||||
"Gen_Delete": "Delete",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Save",
|
||||
"Gen_Saved": "Saved",
|
||||
"Gen_Search": "Search",
|
||||
"Gen_SelectToPreview": "Select to preview",
|
||||
"Gen_Selected_Devices": "Selected Devices:",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Updated successfully",
|
||||
@@ -302,8 +306,8 @@
|
||||
"Gen_Work_In_Progress": "Work in progress, good time to feedback on https://github.com/jokob-sk/NetAlertX/issues",
|
||||
"General_display_name": "General",
|
||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting. If enabled (<code>0</code> is disabled), devices marked as <b>New Device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New Devices</b> after <code>X</code> hours.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Keep new devices for",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices marked as <b>New Device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New Devices</b> after <code>X</code> hours.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Delete new devices after",
|
||||
"HelpFAQ_Cat_Detail": "Details",
|
||||
"HelpFAQ_Cat_Detail_300_head": "What means ",
|
||||
"HelpFAQ_Cat_Detail_300_text_a": "means a network device (a device of the type AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router,USB LAN Adapter, USB WIFI Adapter, or Internet). Custom types can be added via the <code>NETWORK_DEVICE_TYPES</code> setting.",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.",
|
||||
"Reports_Sent_Log": "Sent Reports Log",
|
||||
"SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) rely on scanning specific network interfaces and subnets. Check the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. <br/> <br/> An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlert<sup>X</sup> having access to the network (UNIFI, dhcp.leases, PiHole, etc.). <br/> <br/> Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.",
|
||||
"SCAN_SUBNETS_name": "Networks to scan",
|
||||
"SYSTEM_TITLE": "System Information",
|
||||
"Setting_Override": "Override value",
|
||||
"Setting_Override_Description": "Enabling this option will override an App supplied default value with the value specified above.",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "Show in presence chart",
|
||||
"UI_REFRESH_description": "Enter number of seconds after which the UI reloads. Set to <code>0</code> to disable.",
|
||||
"UI_REFRESH_name": "Auto-refresh UI",
|
||||
"VERSION_description": "Version or timestamp helper value to check if app was upgraded.",
|
||||
"VERSION_name": "Version or timestamp",
|
||||
"devices_old": "Refreshing...",
|
||||
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
|
||||
"general_event_title": "Executing an ad-hoc event",
|
||||
@@ -690,4 +697,4 @@
|
||||
"settings_update_item_warning": "Update the value below. Be careful to follow the previous format. <b>Validation is not performed.</b>",
|
||||
"test_event_icon": "fa-vial-circle-check",
|
||||
"test_event_tooltip": "Save your changes at first before you test your settings."
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,8 @@
|
||||
"BackDevices_Restore_okay": "Restauración ejecutado con éxito.",
|
||||
"BackDevices_darkmode_disabled": "Darkmode Desactivado",
|
||||
"BackDevices_darkmode_enabled": "Darkmode Activado",
|
||||
"CLEAR_NEW_FLAG_description": "Si está habilitado (<code>0</code> está desactivado), los dispositivos marcados como <b>Nuevo dispositivo</b> se desmarcarán si el límite de tiempo (especificado en horas) excede su tiempo de <b>primera sesión</b>.",
|
||||
"CLEAR_NEW_FLAG_name": "Eliminar la nueva bandera",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "Esta es una configuración de mantenimiento. Esto especifica el número de días de entradas de eventos que se guardarán. Todos los eventos anteriores se eliminarán periódicamente.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Eliminar eventos anteriores a",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copiar detalles del dispositivo",
|
||||
@@ -284,6 +286,7 @@
|
||||
"Gen_AreYouSure": "¿Estás seguro?",
|
||||
"Gen_Backup": "Ejecutar copia de seguridad",
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "Cambiar",
|
||||
"Gen_Copy": "Ejecutar",
|
||||
"Gen_DataUpdatedUITakesTime": "Correcto - La interfaz puede tardar en actualizarse si se está ejecutando un escaneo.",
|
||||
"Gen_Delete": "Eliminar",
|
||||
@@ -302,6 +305,7 @@
|
||||
"Gen_Save": "Guardar",
|
||||
"Gen_Saved": "Guardado",
|
||||
"Gen_Search": "Buscar",
|
||||
"Gen_SelectToPreview": "Seleccionar para previsualizar",
|
||||
"Gen_Selected_Devices": "Dispositivos seleccionados:",
|
||||
"Gen_Switch": "Cambiar",
|
||||
"Gen_Upd": "Actualizado correctamente",
|
||||
@@ -312,8 +316,8 @@
|
||||
"Gen_Work_In_Progress": "Trabajo en curso, un buen momento para hacer comentarios en https://github.com/jokob-sk/NetAlertX/issues",
|
||||
"General_display_name": "General",
|
||||
"General_icon": "<i class=\"fa fa-gears\"></i>",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Esta es una configuración de mantenimiento. Si está habilitado (<code>0</code> está deshabilitado), los dispositivos marcados como <b>Nuevo dispositivo</b> se eliminarán si su <b>Primera sesión</b> el tiempo era anterior a las horas especificadas en esta configuración. Utilice esta configuración si desea eliminar automáticamente <b>Nuevos dispositivos</b> después de <code>X</code> horas.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Guardar nuevos dispositivos para",
|
||||
"HRS_TO_KEEP_NEWDEV_description": "Se trata de una configuración de mantenimiento <b>BORRAR dispositivos</b>. Si está activado (<code>0</code> está desactivado), los dispositivos marcados como <b>Nuevo dispositivo</b> se eliminarán si su fecha de <b>primera sesión</b> es anterior a las horas especificadas en este ajuste. Use este ajuste si desea eliminar automáticamente <b>Nuevos dispositivos</b> después de <code>X</code> horas.",
|
||||
"HRS_TO_KEEP_NEWDEV_name": "Eliminar nuevos dispositivos después",
|
||||
"HelpFAQ_Cat_Detail": "Detalles",
|
||||
"HelpFAQ_Cat_Detail_300_head": "¿Qué significa? ",
|
||||
"HelpFAQ_Cat_Detail_300_text_a": "significa un dispositivo de red (un dispositivo del tipo AP, Gateway, Firewall, Hypervisor, Powerline, Switch, WLAN, PLC, Router,Adaptador LAN USB, Adaptador WIFI USB o Internet). Los tipos personalizados pueden añadirse mediante el ajuste <code>NETWORK_DEVICE_TYPES</code>.",
|
||||
@@ -723,6 +727,8 @@
|
||||
"UI_PRESENCE_name": "Mostrar en el gráfico de presencia",
|
||||
"UI_REFRESH_description": "Ingrese el número de segundos después de los cuales se recarga la interfaz de usuario. Ajustado a <code> 0 </code> para desactivar.",
|
||||
"UI_REFRESH_name": "Actualización automática de la interfaz de usuario",
|
||||
"VERSION_description": "Valor de ayuda de versión o marca de tiempo para comprobar si la aplicación se ha actualizado.",
|
||||
"VERSION_name": "Versión o marca de tiempo",
|
||||
"WEBHOOK_PAYLOAD_description": "El formato de datos de carga de Webhook para el atributo <code>body</code> > <code>attachments</code> > <code>text</code> en el json de carga. Vea un ejemplo de la carga <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json\">aquí</a>. (por ejemplo: para discord use <code>text</code>)",
|
||||
"WEBHOOK_PAYLOAD_name": "Tipo de carga",
|
||||
"WEBHOOK_REQUEST_METHOD_description": "El método de solicitud HTTP que se utilizará para la llamada de webhook.",
|
||||
@@ -735,7 +741,7 @@
|
||||
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
|
||||
"Webhooks_settings_group": "<i class=\"fa fa-circle-nodes\"></i> Webhooks",
|
||||
"devices_old": "Volviendo a actualizar....",
|
||||
"general_event_description": "El evento que ha desencadenado puede tardar un tiempo hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vació la siguiente cola de ejecución (compruebe el registro de errores <a href='/maintenance.php#tab_Logging'>si</a> tiene problemas). <br/> <br/> Cola de ejecución:",
|
||||
"general_event_description": "El evento que ha activado puede tardar un poco hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vacía la cola de ejecución a continuación (consulte el <a href='/maintenance.php#tab_Logging'>registro de errores</a> si encuentra problemas). <br/> <br/> Cola de ejecución:",
|
||||
"general_event_title": "Ejecutar un evento ad-hoc",
|
||||
"report_guid": "Guía de las notificaciones:",
|
||||
"report_guid_missing": "No se ha encontrado la notificación vinculada. Hay un pequeño retraso entre las notificaciones enviadas recientemente y su disponibilidad. Actualiza tu página y la caché después de unos segundos. También es posible que la notificación seleccionada se haya eliminado durante el mantenimiento, tal y como se especifica en la configuración <code>de DBCLNP_NOTIFI_HIST</code>. <br/> <br/>En su lugar, se muestra la notificación más reciente. La notificación que falta tiene el siguiente GUID:",
|
||||
|
||||
795
front/php/templates/language/fr_fr.json
Normal file → Executable file
795
front/php/templates/language/fr_fr.json
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Ripristino eseguito correttamente.",
|
||||
"BackDevices_darkmode_disabled": "Modalità scura disabilitata",
|
||||
"BackDevices_darkmode_enabled": "Modalità scura abilitata",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "Questa è un'impostazione di manutenzione. Specifica il numero di giorni delle voci degli eventi che verranno conservati. Tutti gli eventi più vecchi verranno eliminati periodicamente. Si applica anche alla cronologia degli eventi del plugin (Plugin Events History).",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Elimina eventi più vecchi di",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copia dettagli dal dispositivo",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Sei sicuro?",
|
||||
"Gen_Backup": "Esegui backup",
|
||||
"Gen_Cancel": "Annulla",
|
||||
"Gen_Change": "Modifica",
|
||||
"Gen_Copy": "Esegui",
|
||||
"Gen_DataUpdatedUITakesTime": "OK: l'aggiornamento dell'interfaccia utente potrebbe richiedere del tempo se è in esecuzione una scansione.",
|
||||
"Gen_Delete": "Elimina",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Salva",
|
||||
"Gen_Saved": "Salvato",
|
||||
"Gen_Search": "Cerca",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Dispositivi selezionati:",
|
||||
"Gen_Switch": "Cambia",
|
||||
"Gen_Upd": "Aggiornato correttamente",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "Rilevato automaticamente: indica se il dispositivo genera il suo indirizzo MAC casualmente.",
|
||||
"Reports_Sent_Log": "Log rapporti inviati",
|
||||
"SCAN_SUBNETS_description": "La maggior parte degli scanner di rete (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) si basano sulla scansione di interfacce di rete e sottoreti specifiche. Consulta la <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">documentazione sulle sottoreti</a> per assistenza su questa impostazione, in particolare VLAN, quali VLAN sono supportate o come individuare la maschera di rete e l'interfaccia. <br/> <br/> Un'alternativa agli scanner in rete è abilitare altri scanner/importatori di dispositivi che non si affidano a NetAlert<sup>X</sup> che hanno accesso alla rete (UNIFI, dhcp.leases , PiHole, ecc.). <br/> <br/> Nota: il tempo di scansione stesso dipende dal numero di indirizzi IP da controllare, quindi impostalo attentamente con la maschera di rete e l'interfaccia appropriate.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Informazioni sistema",
|
||||
"Setting_Override": "Sovrascrivi valore",
|
||||
"Setting_Override_Description": "L'abilitazione di questa opzione sovrascriverà il valore predefinito fornito dall'app con il valore specificato sopra.",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "Mostra nel grafico delle presenze",
|
||||
"UI_REFRESH_description": "Inserisci il numero di secondi dopo il quale la UI si ricarica. Imposta a <code>0</code> per disabilitare.",
|
||||
"UI_REFRESH_name": "Aggiorna automaticamente la UI",
|
||||
"VERSION_description": "Valore di supporto della versione o della marca temporale per verificare se l'app è stata aggiornata.",
|
||||
"VERSION_name": "Versione o marca temporale",
|
||||
"devices_old": "Aggiornamento...",
|
||||
"general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:",
|
||||
"general_event_title": "Esecuzione di un evento ad-hoc",
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
// ###################################
|
||||
|
||||
$defaultLang = "en_us";
|
||||
$allLanguages = ["en_us","es_es","de_de", "nb_no", "pl_pl", "pt_br", "ru_ru", "fr_fr", "it_it", "zh_cn"];
|
||||
$allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "pt_br", "tr_tr", "zh_cn", "cs_cz"];
|
||||
|
||||
|
||||
global $db;
|
||||
|
||||
@@ -21,6 +22,7 @@ switch($result){
|
||||
case 'Turkish (tr_tr)': $pia_lang_selected = 'tr_tr'; break;
|
||||
case 'French': $pia_lang_selected = 'fr_fr'; break;
|
||||
case 'Chinese (zh_cn)': $pia_lang_selected = 'zh_cn'; break;
|
||||
case 'Czech (cs_cz)': $pia_lang_selected = 'cs_cz'; break;
|
||||
default: $pia_lang_selected = 'en_us'; break;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,6 @@ def merge_translations(main_file, other_files):
|
||||
if __name__ == "__main__":
|
||||
current_path = os.path.dirname(os.path.abspath(__file__))
|
||||
# language codes can be found here: http://www.lingoes.net/en/translator/langcode.htm
|
||||
json_files = ["en_us.json", "de_de.json", "es_es.json", "fr_fr.json", "nb_no.json", "ru_ru.json", "it_it.json", "pt_br.json", "pl_pl.json", "zh_cn.json", "tr_tr.json"]
|
||||
json_files = ["en_us.json", "de_de.json", "es_es.json", "fr_fr.json", "nb_no.json", "ru_ru.json", "it_it.json", "pt_br.json", "pl_pl.json", "zh_cn.json", "tr_tr.json", "cs_cz.json"]
|
||||
file_paths = [os.path.join(current_path, file) for file in json_files]
|
||||
merge_translations(file_paths[0], file_paths[1:])
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Gjenoppretting utført.",
|
||||
"BackDevices_darkmode_disabled": "Mørk modus Deaktivert",
|
||||
"BackDevices_darkmode_enabled": "Mørk modus Aktivert",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "Dette er en vedlikeholdsinnstilling. Dette spesifiserer antall dager verdt med hendelsesoppføringer som vil beholdes. Alle eldre hendelser vil bli slettet med jevne mellomrom. Gjelder også for plugin-hendelseshistorikk.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Slett hendelser eldre enn",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Kopier detaljer fra enhet",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Er du sikker?",
|
||||
"Gen_Backup": "Kjør sikkerhetskopiering",
|
||||
"Gen_Cancel": "Avbryt",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Kjør",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Det kan ta litt tid før brukergrensesnittet oppdateres hvis en skanning kjøres.",
|
||||
"Gen_Delete": "Slett",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Lagre",
|
||||
"Gen_Saved": "Lagret",
|
||||
"Gen_Search": "Søk",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Valgte Enheter:",
|
||||
"Gen_Switch": "Bytt",
|
||||
"Gen_Upd": "Oppdatering vellykket",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "Autodetektert - indikerer om enheten randomiserer MAC-adressen sin.",
|
||||
"Reports_Sent_Log": "Sendte rapport logger",
|
||||
"SCAN_SUBNETS_description": "De fleste skannere på nettet (ARP-Scan, NMAP, NSlookup, Dig, Pholus) er avhengige av å skanne spesifikke nettverksgrensesnitt og undernett. Sjekk <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnett dokumentasjonen</a> for hjelp på denne innstillingen, spesielt VLAN-er, hvilke VLAN-er som støttes, eller hvordan du kan finne ut nettverksmasken og grensesnittet ditt. <br/> <br/> Et alternativ til skannere på nettet er å aktivere noen andre enhetsskannere/importører som ikke er avhengige av Netalert<sup>X</sup> med tilgang til nettverket (UniFi, DHCP-Leaser, Pihole, osv.). <br/> <br/> Merk: Selve skanningstiden avhenger av antall IP -adresser som skal sjekkes, så sett dette opp nøye med riktig nettverksmaske og grensesnitt.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Systeminformasjon",
|
||||
"Setting_Override": "Overstyr verdi",
|
||||
"Setting_Override_Description": "Aktivering av dette alternativet vil overstyre en App som leveres standard-verdi med verdien som er spesifisert ovenfor.",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "Vis i tilstedeværelse-diagrammet",
|
||||
"UI_REFRESH_description": "Skriv inn antall sekunder før UI laster inn på nytt. Sett til <code>0</code> for å deaktivere.",
|
||||
"UI_REFRESH_name": "Oppdater UI automatisk",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Oppdaterer...",
|
||||
"general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:",
|
||||
"general_event_title": "Utfører en ad-hoc hendelse",
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Przywracanie wykonane z sukcesem.",
|
||||
"BackDevices_darkmode_disabled": "Tryb ciemny Wyłączony",
|
||||
"BackDevices_darkmode_enabled": "Tryb ciemny Włączony",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "To jest ustawienie konserwacji. Określa ile dni mają być utrzymywane wpisy wydarzeń. Wszystkie starsze wpisy wydarzeń zostaną usunięte okresowo. Dotyczy także Historii Wydarzeń Pluginów.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Usuń wydarzenia starsze niż",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i>Kopiuj opis z urządzenia",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Jesteś pewien?",
|
||||
"Gen_Backup": "Wykonaj Kopie Zapasową",
|
||||
"Gen_Cancel": "Anuluj",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Wykonaj",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Aktualizacja UI może chwile potrwać jeżeli wykonywany jest skan.",
|
||||
"Gen_Delete": "Usuń",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Zapisz",
|
||||
"Gen_Saved": "Zapisano",
|
||||
"Gen_Search": "Szukaj",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Wybierz Urządzenia:",
|
||||
"Gen_Switch": "Switch",
|
||||
"Gen_Upd": "Zaktualizowane poprawnie",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "Auto wykrywanie - oznacza czy urządzenie randomizuje swój adres MAC.",
|
||||
"Reports_Sent_Log": "Wyślij zgłoszenie logów",
|
||||
"SCAN_SUBNETS_description": "Większość skanerów sieciowych (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) opiera się na konkretnych interfejsach sieciowych oraz podsieci. Sprawdź <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\"> dokumentacji podsieci</a> jeżeli potrzebujesz pomocy w ustawieniach, a szczególnie z VLAN'ami, jakie VLAN'y są wspierane oraz jak rozgryźć maskę podsieci twojego interfejsu.<br/><br/> Alternatywą do skanerów sieciowych jest uruchomienie innego Skanera Urządzeń/Importera który nie polega by NetAlert<sup>X</sup> miał dostęp do sieci (UNIFI, dhcp.leases, PiHole, itp.).<br/><br/> Notatka: Czas skanu zależy od liczby adresów IP do sprawdzenia, więc ustaw go tak by skanował odpowiedni interfejs i maskę sieciową.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Informacje o Systemie",
|
||||
"Setting_Override": "Nadpisz wartość",
|
||||
"Setting_Override_Description": "Włączanie tej opcji nadpisze podstawową wartość na wartość podaną powyżej.",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "Pokaż w tabeli obecności",
|
||||
"UI_REFRESH_description": "Wprowadź liczbę sekund po której UI ma się przeładować. Ustaw na <code>0</code> by wyłączyć.",
|
||||
"UI_REFRESH_name": "Automatycznie odświeżaj UI",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Odświeżanie...",
|
||||
"general_event_description": "Wydarzenie które wyzwoliłeś może chwilę zająć dopóki procesy w tle nie zakończą się. Wykonanie zakończy się kiedy kolejka się opróżni (Sprawdź <a href='/maintenance.php#tab_Logging'>logi błędów</a> jeżeli napotkasz błędy).<br/><br/> Kolejka wykonywania:",
|
||||
"general_event_title": "Wykonywanie wydarzeń ad-hoc",
|
||||
|
||||
7
front/php/templates/language/pt_br.json
Normal file → Executable file
7
front/php/templates/language/pt_br.json
Normal file → Executable file
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Restauração executada com sucesso.",
|
||||
"BackDevices_darkmode_disabled": "Modo Noturno Desabilitado",
|
||||
"BackDevices_darkmode_enabled": "Modo Noturno Habilitado",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "Esta é uma definição de manutenção. Especifica o número de dias de entradas de eventos que serão mantidas. Todos os eventos mais antigos serão eliminados periodicamente. Também se aplica ao Histórico de eventos do plug-in.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Excluir eventos mais antigos que",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copiar detalhes do dispositivo",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Tem certeza?",
|
||||
"Gen_Backup": "Executar backup",
|
||||
"Gen_Cancel": "Cancelar",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Executar",
|
||||
"Gen_DataUpdatedUITakesTime": "OK - Pode levar um tempo para a interface do usuário ser atualizada se uma verificação estiver em execução.",
|
||||
"Gen_Delete": "Excluir",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Salvar",
|
||||
"Gen_Saved": "Salvo",
|
||||
"Gen_Search": "Procurar",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Dispositivos selecionados:",
|
||||
"Gen_Switch": "Trocar",
|
||||
"Gen_Upd": "Atualizado com sucesso",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "Восстановление выполнено успешно.",
|
||||
"BackDevices_darkmode_disabled": "Темный режим отключен",
|
||||
"BackDevices_darkmode_enabled": "Темный режим включен",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "Это настройка обслуживания. Здесь указывается количество дней, в течение которых будут храниться записи о событиях. Все старые события будут периодически удаляться. Также применимо к истории событий плагина.",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "Удалить события старше",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Скопировать данные с устройства",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Вы уверены?",
|
||||
"Gen_Backup": "Запустить резервное копирование",
|
||||
"Gen_Cancel": "Отмена",
|
||||
"Gen_Change": "Изменить",
|
||||
"Gen_Copy": "Запустить",
|
||||
"Gen_DataUpdatedUITakesTime": "ОК - Обновление UI может занять некоторое время, если сканирование выполняется.",
|
||||
"Gen_Delete": "Удалить",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Сохранить",
|
||||
"Gen_Saved": "Сохранено",
|
||||
"Gen_Search": "Поиск",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Выбранные устройства:",
|
||||
"Gen_Switch": "Переключить",
|
||||
"Gen_Upd": "Успешное обновление",
|
||||
@@ -416,7 +420,7 @@
|
||||
"Maintenance_Tool_del_unknowndev_text": "Прежде чем использовать эту функцию, сделайте резервную копию. Удаление невозможно отменить. Все названные устройства (неизвестные) будут удалены из базы данных.",
|
||||
"Maintenance_Tool_displayed_columns_text": "Измените видимость и порядок столбцов на странице <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Устройства</b></a>.",
|
||||
"Maintenance_Tool_drag_me": "Перетащите элемент, чтобы изменить порядок столбцов.",
|
||||
"Maintenance_Tool_order_columns_text": "",
|
||||
"Maintenance_Tool_order_columns_text": "Maintenance_Tool_order_columns_text",
|
||||
"Maintenance_Tool_purgebackup": "Очистить резервные копии",
|
||||
"Maintenance_Tool_purgebackup_noti": "Очистить резервные копии",
|
||||
"Maintenance_Tool_purgebackup_noti_text": "Вы уверены, что хотите удалить все резервные копии, кроме трех последних?",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "Автоматически обнаружено — указывает, рандомизирует ли устройство свой MAC-адрес.",
|
||||
"Reports_Sent_Log": "Отправить журнал логов",
|
||||
"SCAN_SUBNETS_description": "Большинство сетевых сканеров (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) полагаются на сканирование определенных сетевых интерфейсов и подсетей. Дополнительную информацию по этому параметру можно найти в <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">документации по подсетям</a>, особенно VLAN, какие VLAN поддерживаются или как разобраться в маске сети и своем интерфейсе. <br/> <br/> Альтернативой сетевым сканерам является включение некоторых других сканеров/импортеров устройств, которые не полагаются на NetAlert<sup>X</sup>, имеющий доступ к сети (UNIFI, dhcp.leases , PiHole и др.). <br/> <br/> Примечание. Само время сканирования зависит от количества проверяемых IP-адресов, поэтому тщательно настройте его, указав соответствующую маску сети и интерфейс.",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "Системная информация",
|
||||
"Setting_Override": "Переопределить значение",
|
||||
"Setting_Override_Description": "Включение этой опции приведет к переопределению значения по умолчанию, предоставленного приложением, на значение, указанное выше.",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "Показать в диаграмме присутствия",
|
||||
"UI_REFRESH_description": "Введите количество секунд, по истечении которых пользовательский интерфейс перезагружается. Установите значение <code>0</code>, чтобы отключить.",
|
||||
"UI_REFRESH_name": "Автоматическое обновление интерфейса",
|
||||
"VERSION_description": "Вспомогательное значение версии или метки времени, позволяющее проверить, было ли приложение обновлено.",
|
||||
"VERSION_name": "Версия или временная метка",
|
||||
"devices_old": "Актуализируется...",
|
||||
"general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:",
|
||||
"general_event_title": "Выполнение специального события",
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "",
|
||||
"BackDevices_darkmode_disabled": "",
|
||||
"BackDevices_darkmode_enabled": "",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "",
|
||||
"DevDetail_Copy_Device_Title": "",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "Emin misiniz?",
|
||||
"Gen_Backup": "",
|
||||
"Gen_Cancel": "İptal",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "Çalıştır",
|
||||
"Gen_DataUpdatedUITakesTime": "TAMAM - Eğer bir tarama çalışıyorsa arayüzün güncellenmesi biraz zaman alabilir",
|
||||
"Gen_Delete": "Sil",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "Kaydet",
|
||||
"Gen_Saved": "Kaydedildi",
|
||||
"Gen_Search": "",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "Seçilmiş Cihazlar:",
|
||||
"Gen_Switch": "",
|
||||
"Gen_Upd": "Başarılı bir şekilde güncellendi",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "",
|
||||
"Reports_Sent_Log": "",
|
||||
"SCAN_SUBNETS_description": "",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "",
|
||||
"Setting_Override": "",
|
||||
"Setting_Override_Description": "",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "",
|
||||
"UI_REFRESH_description": "",
|
||||
"UI_REFRESH_name": "",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "Yenileniyor...",
|
||||
"general_event_description": "",
|
||||
"general_event_title": "",
|
||||
@@ -690,4 +697,4 @@
|
||||
"settings_update_item_warning": "",
|
||||
"test_event_icon": "",
|
||||
"test_event_tooltip": ""
|
||||
}
|
||||
}
|
||||
7
front/php/templates/language/zh_cn.json
Normal file → Executable file
7
front/php/templates/language/zh_cn.json
Normal file → Executable file
@@ -56,6 +56,8 @@
|
||||
"BackDevices_Restore_okay": "已成功恢复。",
|
||||
"BackDevices_darkmode_disabled": "暗黑模式已禁用",
|
||||
"BackDevices_darkmode_enabled": "已启用暗黑模式",
|
||||
"CLEAR_NEW_FLAG_description": "",
|
||||
"CLEAR_NEW_FLAG_name": "",
|
||||
"DAYS_TO_KEEP_EVENTS_description": "这是维护设置。它指定将保留的事件条目的天数。所有较旧的事件将被定期删除。也适用于插件事件历史记录。",
|
||||
"DAYS_TO_KEEP_EVENTS_name": "删除早于",
|
||||
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> 从设备复制详细信息",
|
||||
@@ -274,6 +276,7 @@
|
||||
"Gen_AreYouSure": "你确定吗?",
|
||||
"Gen_Backup": "运行备份",
|
||||
"Gen_Cancel": "取消",
|
||||
"Gen_Change": "",
|
||||
"Gen_Copy": "运行",
|
||||
"Gen_DataUpdatedUITakesTime": "好的 - 如果扫描正在运行,UI 可能需要一段时间才能更新。",
|
||||
"Gen_Delete": "删除",
|
||||
@@ -292,6 +295,7 @@
|
||||
"Gen_Save": "保存",
|
||||
"Gen_Saved": "已保存",
|
||||
"Gen_Search": "搜索",
|
||||
"Gen_SelectToPreview": "",
|
||||
"Gen_Selected_Devices": "选定的设备:",
|
||||
"Gen_Switch": "交换",
|
||||
"Gen_Upd": "已成功更新",
|
||||
@@ -556,6 +560,7 @@
|
||||
"RandomMAC_hover": "自动检测 - 表示设备是否随机化其 MAC 地址。",
|
||||
"Reports_Sent_Log": "已发送报告日志",
|
||||
"SCAN_SUBNETS_description": "大多数网络扫描器(ARP-SCAN、NMAP、NSLOOKUP、DIG、PHOLUS)依赖于扫描特定的网络接口和子网。查看<a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">子网文档</a>以获取有关此设置的帮助,尤其是 VLAN、支持哪些 VLAN,或者如何确定网络掩码和接口。<br/> <br/> 网络扫描器的替代方法是启用一些其他不依赖于 NetAlert<sup>X</sup> 访问网络的设备扫描器/导入器(UNIFI、dhcp.leases、PiHole 等)。<br/> <br/> 注意:扫描时间本身取决于要检查的 IP 地址数量,因此请使用适当的网络掩码和接口仔细设置。",
|
||||
"SCAN_SUBNETS_name": "",
|
||||
"SYSTEM_TITLE": "系统信息",
|
||||
"Setting_Override": "覆盖值",
|
||||
"Setting_Override_Description": "启用此选项将用上面指定的值覆盖应用程序提供的默认值。",
|
||||
@@ -654,6 +659,8 @@
|
||||
"UI_PRESENCE_name": "在存在图表中显示",
|
||||
"UI_REFRESH_description": "输入界面重新加载的秒数。设置为 <code>0</code> 可禁用。",
|
||||
"UI_REFRESH_name": "自动刷新界面",
|
||||
"VERSION_description": "",
|
||||
"VERSION_name": "",
|
||||
"devices_old": "刷新中...",
|
||||
"general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:",
|
||||
"general_event_title": "执行自组织网络事件",
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// ## GUI settings processing start
|
||||
// ###################################
|
||||
|
||||
if( isset($_COOKIE['Front_Dark_Mode_Enabled']))
|
||||
if( isset($_COOKIE['UI_dark_mode']))
|
||||
{
|
||||
$ENABLED_DARKMODE = $_COOKIE['Front_Dark_Mode_Enabled'] == "true";
|
||||
$ENABLED_DARKMODE = $_COOKIE['UI_dark_mode'] == "True";
|
||||
}else
|
||||
{
|
||||
$ENABLED_DARKMODE = False;
|
||||
|
||||
@@ -11,12 +11,12 @@ NetAlertX supports additional plugins to extend its functionality, each with its
|
||||
> You can load additional Plugins via the General -> `LOADED_PLUGINS` setting. Use `Ctrl + Click` to select/deselect.
|
||||
|
||||
1. Pick your `🔍 dev scanner` plugin (e.g. `ARPSCAN` or `NMAPDEV`), or import devices into the application with an `📥 importer` plugin. (See **✅Enabling plugins** below)
|
||||
1. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
||||
1. Setup your [Network topology diagram](/docs/NETWORK_TREE.md)
|
||||
1. Fine-tune [Notifications](/docs/NOTIFICATIONS.md)
|
||||
1. [Backup your setup](/docs/BACKUPS.md)
|
||||
1. Contribute and [Create custom plugins](/docs/PLUGINS_DEV.md)
|
||||
1. Consider [donating](https://github.com/jokob-sk/NetAlertX?tab=readme-ov-file#-sponsors) to keep me going
|
||||
2. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
||||
3. Setup your [Network topology diagram](/docs/NETWORK_TREE.md)
|
||||
4. Fine-tune [Notifications](/docs/NOTIFICATIONS.md)
|
||||
5. [Backup your setup](/docs/BACKUPS.md)
|
||||
6. Contribute and [Create custom plugins](/docs/PLUGINS_DEV.md)
|
||||
7. Consider [donating](https://github.com/jokob-sk/NetAlertX?tab=readme-ov-file#-sponsors) to keep me going
|
||||
|
||||
|
||||
## 📑 Available Plugins
|
||||
@@ -53,6 +53,7 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T
|
||||
| `SMTP` | ▶️ | Email notifications | | | Script | [_publisher_email](/front/plugins/_publisher_email/) |
|
||||
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | | Script | [snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| `SYNC` | 🔍/⚙/📥| Sync & import from NetAlertX instances | 🖧 🔄 | | Script | [sync](/front/plugins/sync/) |
|
||||
| `TELEGRAM` | ▶️ | Telegram notifications | | | Script | [_publisher_telegram](/front/plugins/_publisher_telegram/) |
|
||||
| `UNDIS` | 🔍/📥 | Create dummy devices | | | Script | [undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| `UNFIMP` | 🔍/📥 | UniFi device import & sync | 🖧 | | Script | [unifi_import](/front/plugins/unifi_import/) |
|
||||
| `VNDRPDT` | ⚙ | Vendor database update | | | Script | [vendor_update](/front/plugins/vendor_update/) |
|
||||
|
||||
@@ -767,8 +767,8 @@
|
||||
{ "elementType": "select", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": 1,
|
||||
"options": [1, 2],
|
||||
"default_value": 5,
|
||||
"options": [3, 5],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
@@ -779,7 +779,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Paho MQTT API version. Depends on the MQTT <a href=\"https://eclipse.dev/paho/files/paho.mqtt.python/html/index.html#callbacks\" target=\"_blank\">version supported by the MQTT broker</a>. Usually set to <code>1</code>."
|
||||
"string": "MQTT Protocol version. Depends on the MQTT broker</a>. Usually set to <code>5</code>, or <code>3</code> for backwards compatibility."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -271,20 +271,23 @@ def create_sensor(mqtt_client, deviceId, deviceName, sensorType, sensorName, ico
|
||||
return sensorConfig
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def mqtt_create_client():
|
||||
def mqtt_create_client():
|
||||
|
||||
mytransport = 'tcp' # or 'websockets'
|
||||
|
||||
def on_disconnect(mqtt_client, userdata, reason_code):
|
||||
|
||||
global mqtt_connected_to_broker
|
||||
|
||||
# REF: If we wanted a auto reconnect, a good source is here: https://www.emqx.com/en/blog/how-to-use-mqtt-in-python
|
||||
mqtt_connected_to_broker = False
|
||||
|
||||
# not sure is below line is correct / necessary
|
||||
# client = mqtt_create_client()
|
||||
mylog('debug', [f"[{pluginName}] Connection terminated, reason_code: {reason_code}"])
|
||||
|
||||
def on_connect(mqtt_client, userdata, flags, reason_code):
|
||||
def on_connect(mqtt_client, userdata, flags, reason_code, properties):
|
||||
|
||||
global mqtt_connected_to_broker
|
||||
|
||||
# REF: Good docu on reason codes: https://www.emqx.com/en/blog/mqtt5-new-features-reason-code-and-ack
|
||||
if reason_code == 0:
|
||||
mylog('verbose', [f"[{pluginName}] Connected to broker"])
|
||||
mqtt_connected_to_broker = True # Signal connection
|
||||
@@ -292,21 +295,29 @@ def mqtt_create_client():
|
||||
mylog('verbose', [f"[{pluginName}] Connection failed, reason_code: {reason_code}"])
|
||||
mqtt_connected_to_broker = False
|
||||
|
||||
|
||||
global mqtt_client
|
||||
|
||||
if get_setting_value('MQTT_VERSION') == 1:
|
||||
mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1)
|
||||
# Paho will be soon not supporting V1 anymore, so this really should not be a user choice to start with
|
||||
# This code now uses V2 by default
|
||||
# Ref: https://eclipse.dev/paho/files/paho.mqtt.python/html/migrations.html
|
||||
|
||||
if get_setting_value('MQTT_VERSION') == 3:
|
||||
version = mqtt.MQTTv311
|
||||
else:
|
||||
mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
||||
version = mqtt.MQTTv5
|
||||
|
||||
mqtt_client = mqtt.Client(
|
||||
callback_api_version = mqtt.CallbackAPIVersion.VERSION2,
|
||||
transport=mytransport,
|
||||
protocol=mqtt.MQTTv5)
|
||||
mqtt_client.on_connect = on_connect
|
||||
mqtt_client.on_disconnect = on_disconnect
|
||||
|
||||
if get_setting_value('MQTT_TLS'):
|
||||
mqtt_client.tls_set()
|
||||
|
||||
mqtt_client.username_pw_set(get_setting_value('MQTT_USER'), get_setting_value('MQTT_PASSWORD'))
|
||||
mqtt_client.on_connect = on_connect
|
||||
mqtt_client.on_disconnect = on_disconnect
|
||||
mqtt_client.connect(get_setting_value('MQTT_BROKER'), get_setting_value('MQTT_PORT'))
|
||||
mqtt_client.username_pw_set(username = get_setting_value('MQTT_USER'), password = get_setting_value('MQTT_PASSWORD'))
|
||||
mqtt_client.connect(host = get_setting_value('MQTT_BROKER'), port = get_setting_value('MQTT_PORT'))
|
||||
mqtt_client.loop_start()
|
||||
|
||||
return mqtt_client
|
||||
|
||||
10
front/plugins/_publisher_telegram/README.md
Executable file
10
front/plugins/_publisher_telegram/README.md
Executable file
@@ -0,0 +1,10 @@
|
||||
## Overview
|
||||
|
||||
You can send notifications via Telegram
|
||||
## Notes
|
||||
|
||||
You need Telegram bot to send notifications
|
||||
|
||||
### Usage
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
470
front/plugins/_publisher_telegram/config.json
Executable file
470
front/plugins/_publisher_telegram/config.json
Executable file
@@ -0,0 +1,470 @@
|
||||
{
|
||||
"code_name": "_publisher_telegram",
|
||||
"unique_prefix": "TELEGRAM",
|
||||
"plugin_type": "publisher",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram publisher"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "<i class=\"fa-solid fa-bullhorn\"></i>"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to publish a notification via Telegram."
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"database_column_definitions": [
|
||||
{
|
||||
"column": "Index",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Plugin",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_PrimaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "url",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Object_SecondaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeCreated",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Sent when"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "DateTimeChanged",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Changed"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cambiado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value1",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "eval",
|
||||
"default_value": "",
|
||||
"options": [
|
||||
{
|
||||
"type": "eval",
|
||||
"param": "`<a href='/report.php?guid=${value}'>${value}</a>`"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Notification GUID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"css_classes": "col-sm-8",
|
||||
"show": true,
|
||||
"type": "textarea_readonly",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Result"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value3",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value4",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "N/A"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "UserData",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "textbox_save",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Comments"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comentarios"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Status",
|
||||
"css_classes": "col-sm-1",
|
||||
"show": false,
|
||||
"type": "replace",
|
||||
"default_value": "",
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "missing-in-last-scan",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Status"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Estado"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "Extra",
|
||||
"css_classes": "col-sm-3",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Extra"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Extra"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"function": "RUN",
|
||||
"events": ["test"],
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "select", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "disabled",
|
||||
"options": ["disabled", "on_notification"],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "When to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Cuando ejecuta"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enable sending notifications via a Telegram messanger"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "readonly": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": "python3 /app/front/plugins/_publisher_telegram/tg.py",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Command to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Comando a ejecutar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 10,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Run timeout"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo de espera de ejecución"
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string": "Wartezeit"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "HOST",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "input", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram chat id"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram chat id. If you want to send messages to user, paste user id (Example: <code>1234123412</code>)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "URL",
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "input", "elementOptions": [], "transformers": [] }
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram bot token"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Telegram bot token. You cat get at from <a target=\"_blank\" href=\"https://t.me/BotFather\">BotFather</a>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "SIZE",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": 1024,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Max payload size"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Tamaño máximo de carga útil"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "The maximum size of the 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."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
124
front/plugins/_publisher_telegram/tg.py
Executable file
124
front/plugins/_publisher_telegram/tg.py
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH = "/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
import conf
|
||||
from const import confFileName
|
||||
from plugin_helper import Plugin_Objects
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
from pytz import timezone
|
||||
|
||||
# Make sure the TIMEZONE for logging is correct
|
||||
conf.tz = timezone(get_setting_value('TIMEZONE'))
|
||||
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
|
||||
pluginName = 'TELEGRAM'
|
||||
|
||||
|
||||
def main():
|
||||
mylog('verbose', [f'[{pluginName}](publisher) In script'])
|
||||
|
||||
# Check if basic config settings supplied
|
||||
if check_config() == False:
|
||||
mylog('none', [
|
||||
f'[{pluginName}] ⚠ ERROR: Publisher notification gateway not set up correctly. Check your {confFileName} {pluginName}_* variables.'])
|
||||
return
|
||||
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Notification_obj instance
|
||||
notifications = Notification_obj(db)
|
||||
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
# Send notification
|
||||
result = send(notification["Text"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
primaryId=pluginName,
|
||||
secondaryId=timeNowTZ(),
|
||||
watched1=notification["GUID"],
|
||||
watched2=result,
|
||||
watched3='null',
|
||||
watched4='null',
|
||||
extra='null',
|
||||
foreignKey=notification["GUID"]
|
||||
)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
return True
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
def send(text):
|
||||
# limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB)
|
||||
limit = get_setting_value('TELEGRAM_SIZE')
|
||||
|
||||
if len(text) > limit:
|
||||
payloadData = text[:limit] + " (text was truncated)"
|
||||
else:
|
||||
payloadData = text
|
||||
|
||||
try:
|
||||
# try runnning a subprocess
|
||||
|
||||
req = """curl --location 'https://api.telegram.org/bot%s/sendMessage' \\
|
||||
--header 'Content-Type: application/json' \\
|
||||
--data '{
|
||||
"chat_id": "%s",
|
||||
"text": "%s",
|
||||
"disable_notification": false
|
||||
}'""" % (get_setting_value('TELEGRAM_URL'), get_setting_value('TELEGRAM_HOST'), payloadData)
|
||||
|
||||
mylog('debug', [req])
|
||||
|
||||
p = subprocess.Popen(req, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
# write stdout and stderr into .log files for debugging if needed
|
||||
# Log the stdout and stderr
|
||||
mylog('debug', [stdout, stderr])
|
||||
|
||||
# log result
|
||||
result = stdout
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occurred, handle it
|
||||
mylog('none', [e.output])
|
||||
|
||||
# log result
|
||||
result = e.output
|
||||
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
BIN
front/plugins/_publisher_webhook/Discord_Config.png
Executable file
BIN
front/plugins/_publisher_webhook/Discord_Config.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
@@ -6,3 +6,7 @@ A plugin to publish a notification via the Webhook gateway. Webhooks help you to
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
|
||||
#### Sample Discord Setup
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -44,12 +44,13 @@ def main():
|
||||
HRS_TO_KEEP_NEWDEV = int(values.hourstokeepnewdevice.split('=')[1])
|
||||
DAYS_TO_KEEP_EVENTS = int(values.daystokeepevents.split('=')[1])
|
||||
PHOLUS_DAYS_DATA = get_setting_value("PHOLUS_DAYS_DATA")
|
||||
CLEAR_NEW_FLAG = get_setting_value("CLEAR_NEW_FLAG")
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
|
||||
|
||||
# Execute cleanup/upkeep
|
||||
cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST)
|
||||
cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG)
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Cleanup complete'])
|
||||
|
||||
@@ -58,7 +59,7 @@ def main():
|
||||
#===============================================================================
|
||||
# Cleanup / upkeep database
|
||||
#===============================================================================
|
||||
def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST):
|
||||
def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG):
|
||||
"""
|
||||
Cleaning out old records from the tables that don't need to keep all data.
|
||||
"""
|
||||
@@ -147,8 +148,20 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
# Cleanup New Devices
|
||||
if HRS_TO_KEEP_NEWDEV != 0:
|
||||
mylog('verbose', [f'[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)'])
|
||||
cursor.execute (f"""DELETE FROM Devices
|
||||
WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""")
|
||||
query = f"""DELETE FROM Devices WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '-{str(HRS_TO_KEEP_NEWDEV)} hour')"""
|
||||
mylog('verbose', [f'[{pluginName}] Query: {query} '])
|
||||
cursor.execute (query)
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Clear New Flag
|
||||
if CLEAR_NEW_FLAG != 0:
|
||||
mylog('verbose', [f'[{pluginName}] Devices: Clear "New Device" flag for all devices older than {str(CLEAR_NEW_FLAG)} hours (CLEAR_NEW_FLAG setting)'])
|
||||
query = f"""UPDATE Devices SET dev_NewDevice = 0 WHERE dev_NewDevice = 1 AND date(dev_FirstConnection, '+{str(CLEAR_NEW_FLAG)} hour') < date('now')"""
|
||||
# select * from Devices where dev_NewDevice = 1 AND date(dev_FirstConnection, '+3 hour' ) < date('now')
|
||||
mylog('verbose', [f'[{pluginName}] Query: {query} '])
|
||||
cursor.execute(query)
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup Pholus_Scan
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"code_name": "mikrotik_scan",
|
||||
"unique_prefix": "MTSCAN",
|
||||
"plugin_type": "other",
|
||||
"plugin_type": "device_scanner",
|
||||
"execution_order" : "Layer_4",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
@@ -11,7 +11,7 @@
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Mikrotik (Name discovery)"
|
||||
"string": "Mikrotik (Device discovery)"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
@@ -23,7 +23,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to discover device names."
|
||||
"string": "A plugin to discover devices via Mikrotik."
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# test script by running:
|
||||
# tbc
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
@@ -40,42 +38,35 @@ pluginName = 'MTSCAN'
|
||||
|
||||
def main():
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
mylog('verbose', [f'[{pluginName}] In script'])
|
||||
|
||||
mt_host = get_setting_value('MTSCAN_MT_HOST')
|
||||
mt_port = get_setting_value('MTSCAN_MT_PORT')
|
||||
mt_user = get_setting_value('MTSCAN_MT_USER')
|
||||
mt_password = get_setting_value('MTSCAN_MT_PASS')
|
||||
|
||||
#mylog('verbose', [f'[{pluginName}] Router: {mt_host}:{mt_port} user: {mt_user}, pass: {mt_password}'])
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
# init global variables
|
||||
global MT_HOST, MT_PORT, MT_USER, MT_PASS
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Device_obj instance
|
||||
device_handler = Device_obj(db)
|
||||
# Mikrotik settings
|
||||
MT_HOST = get_setting_value('MTSCAN_MT_HOST')
|
||||
MT_PORT = get_setting_value('MTSCAN_MT_PORT')
|
||||
MT_USER = get_setting_value('MTSCAN_MT_USER')
|
||||
MT_PASS = get_setting_value('MTSCAN_MT_PASS')
|
||||
|
||||
# Retrieve devices
|
||||
#unknown_devices = device_handler.getUnknown()
|
||||
#mylog('verbose', [f'[{pluginName}] Unknown devices count: {len(unknown_devices)}'])
|
||||
plugin_objects = get_entries(plugin_objects)
|
||||
|
||||
all_devices = device_handler.getAll()
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Scan finished, found {len(plugin_objects)} devices'])
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] all devices count: {len(all_devices)}'])
|
||||
|
||||
device_map = {d['dev_MAC']:d['dev_LastIP'] for d in all_devices}
|
||||
def get_entries(plugin_objects: Plugin_Objects) -> Plugin_Objects:
|
||||
|
||||
try:
|
||||
# connect router
|
||||
api = connect(username=mt_user, password=mt_password, host=mt_host, port=mt_port)
|
||||
api = connect(username=MT_USER, password=MT_PASS, host=MT_HOST, port=MT_PORT)
|
||||
|
||||
# get dhcp leases
|
||||
leases = api('/ip/dhcp-server/lease/print')
|
||||
|
||||
|
||||
|
||||
for lease in leases:
|
||||
lease_id = lease.get('.id')
|
||||
@@ -84,56 +75,31 @@ def main():
|
||||
host_name = lease.get('host-name')
|
||||
comment = lease.get('comment')
|
||||
last_seen = lease.get('last-seen')
|
||||
status = lease.get('status')
|
||||
|
||||
mylog('verbose', [f"ID: {lease_id}, Address: {address}, MAC Address: {mac_address}, Host Name: {host_name}, Comment: {comment}, Last Seen: {last_seen}"])
|
||||
if mac_address in device_map.keys():
|
||||
device_name = host_name
|
||||
if comment != '':
|
||||
device_name = comment
|
||||
|
||||
mylog('verbose', [f"ID: {lease_id}, Address: {address}, MAC Address: {mac_address}, Host Name: {host_name}, Comment: {comment}, Last Seen: {last_seen}, Status: {status}"])
|
||||
|
||||
if (status == "bound"):
|
||||
plugin_objects.add_object(
|
||||
# "Name-MAC", "LastIP", "IP", "Name","Host","LastSeen","Comment"
|
||||
primaryId = mac_address,
|
||||
secondaryId = device_map[mac_address],
|
||||
secondaryId = '',
|
||||
watched1 = address,
|
||||
watched2 = device_name,
|
||||
watched3 = host_name,
|
||||
watched4 = last_seen,
|
||||
watched2 = host_name,
|
||||
watched3 = last_seen,
|
||||
watched4 = '',
|
||||
extra = '',
|
||||
helpVal1 = comment,
|
||||
foreignKey = mac_address)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
except TrapError as e:
|
||||
mylog('error', [f"An error occurred: {e}"])
|
||||
except Exception as e:
|
||||
mylog('error', [f"Failed to connect to MikroTik API: {e}"])
|
||||
|
||||
|
||||
#for device in unknown_devices:
|
||||
# domain_name, dns_server = execute_nslookup(device['dev_LastIP'], timeout)
|
||||
|
||||
# if domain_name != '':
|
||||
# plugin_objects.add_object(
|
||||
# # "MAC", "IP", "Server", "Name"
|
||||
# primaryId = device['dev_MAC'],
|
||||
# secondaryId = device['dev_LastIP'],
|
||||
# watched1 = dns_server,
|
||||
# watched2 = domain_name,
|
||||
# watched3 = '',
|
||||
# watched4 = '',
|
||||
# extra = '',
|
||||
# foreignKey = device['dev_MAC'])
|
||||
|
||||
#plugin_objects.write_result_file()
|
||||
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Script finished'])
|
||||
|
||||
return 0
|
||||
return plugin_objects
|
||||
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# BEGIN
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-2" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this, false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
@@ -219,7 +219,7 @@
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-3" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
@@ -230,7 +230,7 @@
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-sm-3" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
@@ -261,7 +261,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "All the newly discovered device names are clened up by applying the following REGEX expression in this order. All the below are replaced by a blank string."
|
||||
"string": "All the newly discovered device names are cleaned up by applying the following REGEX expression in this order. All the below are replaced by a blank string."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -977,7 +977,27 @@
|
||||
"type": {
|
||||
"dataType": "string",
|
||||
"elements": [
|
||||
{ "elementType": "select", "elementOptions": [], "transformers": [] }
|
||||
{
|
||||
"elementType": "span",
|
||||
"elementOptions": [
|
||||
{ "cssClasses": "input-group-addon iconPreview" },
|
||||
{ "getStringKey": "Gen_SelectToPreview" },
|
||||
{ "customId": "NEWDEV_dev_Icon_preview" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{
|
||||
"onChange": "updateIconPreview(this)"
|
||||
},
|
||||
{ "customParams": "NEWDEV_dev_Icon,NEWDEV_dev_Icon_preview" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": "",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NMAP-scan is a command-line tool to discover and fingerprint IP hosts on the local network. The NMAP-scan (and other Network-scan plugin times using the `SCAN_SUBNETS` setting) time depends on the number of IP addresses to check so set this up carefully with the appropriate network mask and interface. Check the [subnets documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) for help with setting up VLANs, what VLANs are supported, or how to figure out the network mask and your interface.
|
||||
|
||||
> [!NOTE]
|
||||
> The `NMAPDEV` plugin is great for detecting the availability of devices, however ARP scan might be better covering multiple VLANS. You can always combine different scan methods. You can find all available network scanning options (marked as `🔍 dev scanner`) in the [Plugins overview](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) readme.
|
||||
> The `NMAPDEV` plugin is great for detecting the availability of devices, however ARP scan might be better covering multiple VLANS and subnets as NMAP can't pickup the MAC address from other subnets (this is an NMAP limitation) which are necessary to identify a device. You can always combine different scan methods. You can find all available network scanning options (marked as `🔍 dev scanner`) in the [Plugins overview](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/README.md) readme.
|
||||
|
||||
### Usage
|
||||
|
||||
|
||||
@@ -1057,7 +1057,7 @@ def main():
|
||||
elif values.rdns_scanning:
|
||||
file_print_pr("[DEBUG] Timestamp 45: ", timeNow())
|
||||
dns_query=None
|
||||
ipn = ipaddress.ip_network(values.rdns_scanning)
|
||||
ipn = ipaddress.ip_network(values.rdns_scanning, strict=False)
|
||||
for ip in ipn.hosts():
|
||||
the_query = ip.reverse_pointer
|
||||
if not dns_query:
|
||||
|
||||
@@ -1,41 +1,63 @@
|
||||
## Overview
|
||||
|
||||
Synchronization plugin to synchronize multiple app instances. The Plugin can sychronize 2 types of data:
|
||||
The synchronization plugin is designed to synchronize data across multiple instances of the app. It supports the following data synchronization modes:
|
||||
|
||||
1. 💻 Devices: The plugin sends an encrypted `table_devices.json` file to synchronize the whole Devices DB table.
|
||||
1. 🔌 Plugin data: The plugin sends encrypted `last_result.log` files for individual plugins.
|
||||
1. **💻 Devices**: Sends an encrypted `table_devices.json` file to synchronize the entire Devices database table.
|
||||
2. **🔌 Plugin Data**: Sends encrypted `last_result.log` files for individual plugins.
|
||||
|
||||
> [!TIP]
|
||||
> `[n]` indicates a setting that is usually specified for the node instance. `[n,h]` indicates a setting used both, on the node and on the hub instance.
|
||||
> **Note:** `[n]` indicates a setting specified for the node instance, and `[n,h]` indicates a setting used on both the node and the hub instances.
|
||||
|
||||
### Synchronizing 💻 Devices data or 🔌 Plugins data
|
||||
### Synchronization Modes
|
||||
|
||||
Most of the setups will probably only use 💻 Devices synchronization. 🔌 Plugins data will be probably used in only special use cases.
|
||||
The plugin operates in three different modes based on the configuration settings:
|
||||
|
||||
#### [n] Node (Source) Settings
|
||||
1. **Mode 1: PUSH (NODE)** - Sends data from the node to the hub.
|
||||
- This mode is activated if `SYNC_hub_url` is set and either `SYNC_devices` or `SYNC_plugins` is enabled.
|
||||
- **Actions**:
|
||||
- Sends `table_devices.json` to the hub if `SYNC_devices` is enabled.
|
||||
- Sends individual plugin `last_result.log` files to the hub if `SYNC_plugins` is enabled.
|
||||
|
||||
- When to run [n,h] `SYNC_RUN`
|
||||
- Schedule [n,h] `SYNC_RUN_SCHD`
|
||||
- API token [n,h] `SYNC_api_token`
|
||||
- Encryption Key [n,h] `SYNC_encryption_key`
|
||||
- Node name [n] `SYNC_node_name`
|
||||
- Hub URL [n] `SYNC_hub_url`
|
||||
- Sync Devices [n] `SYNC_devices` or Sync Plugins [n] `SYNC_plugins` (or both)
|
||||
2. **Mode 2: PULL (HUB)** - Retrieves data from nodes to the hub.
|
||||
- This mode is activated if `SYNC_nodes` is set.
|
||||
- **Actions**:
|
||||
- Retrieves data from configured nodes using the API and saves it locally for further processing.
|
||||
|
||||
#### [h] Hub (Target) Settings
|
||||
3. **Mode 3: RECEIVE (HUB)** - Processes received data on the hub.
|
||||
- Activated when data is received in Mode 2 and is ready to be processed.
|
||||
- **Actions**:
|
||||
- Decodes received data files, processes them, and updates the Devices table accordingly.
|
||||
|
||||
- When to run [n,h] `SYNC_RUN`
|
||||
- Schedule [n,h] `SYNC_RUN_SCHD`
|
||||
- API token [n,h] `SYNC_api_token`
|
||||
- Encryption Key [n,h] `SYNC_encryption_key`
|
||||
### Settings
|
||||
|
||||
#### Node (Source) Settings `[n]`
|
||||
|
||||
- **When to Run** `[n,h]`: `SYNC_RUN`
|
||||
- **Schedule** `[n,h]`: `SYNC_RUN_SCHD`
|
||||
- **API Token** `[n,h]`: `SYNC_api_token`
|
||||
- **Encryption Key** `[n,h]`: `SYNC_encryption_key`
|
||||
- **Node Name** `[n]`: `SYNC_node_name`
|
||||
- **Hub URL** `[n]`: `SYNC_hub_url`
|
||||
- **Sync Devices** `[n]`: `SYNC_devices`
|
||||
- **Sync Plugins** `[n]`: `SYNC_plugins`
|
||||
|
||||
#### Hub (Target) Settings `[h]`
|
||||
|
||||
- **When to Run** `[n,h]`: `SYNC_RUN`
|
||||
- **Schedule** `[n,h]`: `SYNC_RUN_SCHD`
|
||||
- **API Token** `[n,h]`: `SYNC_api_token`
|
||||
- **Encryption Key** `[n,h]`: `SYNC_encryption_key`
|
||||
- **Nodes to Pull From** `[h]`: `SYNC_nodes`
|
||||
|
||||
### Usage
|
||||
|
||||
- Head to **Settings** > **Sync Hub** to adjust the default values.
|
||||
1. **Adjust Settings**:
|
||||
- Navigate to **Settings** > **Sync Hub** to modify default settings.
|
||||
2. **Data Flow**:
|
||||
- Nodes send or receive data based on the specified modes, either pushing data to the hub or pulling from nodes.
|
||||
|
||||
### Notes
|
||||
|
||||
- If a MAC address already exists on the hub, the device will be skipped in the data coming from this SYNC plugin.
|
||||
- Existing devices on the hub will not be updated by the data received from this SYNC plugin if their MAC addresses are already present.
|
||||
- It is recommended to use Device synchronization primarily. Plugin data synchronization is more suitable for specific use cases.
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -159,6 +159,81 @@
|
||||
"string": "Encryption key used to encrypt the data before sending and for decryption on the hub. The key needs to be the same on the hub and on the nodes."
|
||||
}
|
||||
]
|
||||
},{
|
||||
"function": "nodes",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [
|
||||
{ "placeholder": "Enter full url" },
|
||||
{ "suffix": "_in" },
|
||||
{ "cssClasses": "col-sm-10" },
|
||||
{ "prefillValue": "null" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this, false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "multiple": "true" },
|
||||
{ "readonly": "true" },
|
||||
{ "editable": "true" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": [],
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Nodes [h]"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "If specified, the hub will pull Devices data from the listed nodes."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "hub_url",
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
// External files
|
||||
require '/app/front/php/server/init.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// ----------------------------------------------
|
||||
// Method to check authorization
|
||||
function checkAuthorization($method) {
|
||||
// Retrieve the authorization header
|
||||
$headers = apache_request_headers();
|
||||
$auth_header = $headers['Authorization'] ?? '';
|
||||
@@ -14,16 +17,56 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($auth_header !== $expected_token) {
|
||||
http_response_code(403);
|
||||
echo 'Forbidden';
|
||||
write_notification("[Plugin: SYNC] Incoming data: Incorrect API Token", "alert");
|
||||
write_notification("[Plugin: SYNC] Incoming data: Incorrect API Token (".$method.")", "alert");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// Function to return JSON response
|
||||
function jsonResponse($status, $data = '', $message = '') {
|
||||
http_response_code($status);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'node_name' => getSettingValue('SYNC_node_name'),
|
||||
'status' => $status,
|
||||
'message' => $message,
|
||||
'data_base64' => $data,
|
||||
'timestamp' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// MAIN
|
||||
// ----------------------------------------------
|
||||
|
||||
|
||||
// requesting data (this is a NODE)
|
||||
if ($method === 'GET') {
|
||||
checkAuthorization($method);
|
||||
|
||||
$file_path = "/app/front/api/table_devices.json";
|
||||
|
||||
$data = file_get_contents($file_path);
|
||||
|
||||
// Prepare the data to return as a JSON response
|
||||
$response_data = base64_encode($data);
|
||||
|
||||
// Return JSON response
|
||||
jsonResponse(200, $response_data, 'OK');
|
||||
|
||||
write_notification("[Plugin: SYNC] Data sent", "info");
|
||||
|
||||
}
|
||||
// receiving data (this is a HUB)
|
||||
else if ($method === 'POST') {
|
||||
checkAuthorization($method);
|
||||
|
||||
// Retrieve and decode the data from the POST request
|
||||
$data = $_POST['data'] ?? '';
|
||||
$plugin_folder = $_POST['plugin_folder'] ?? '';
|
||||
$node_name = $_POST['node_name'] ?? '';
|
||||
|
||||
|
||||
$storage_path = "/app/front/plugins/{$plugin_folder}";
|
||||
|
||||
// Create the storage directory if it doesn't exist
|
||||
@@ -43,12 +86,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
$file_path = "{$storage_path}/last_result.encoded.{$node_name}.{$file_count}.log";
|
||||
|
||||
|
||||
// Save the decoded data to the file
|
||||
file_put_contents($file_path, $data);
|
||||
http_response_code(200);
|
||||
echo 'Data received and stored successfully';
|
||||
write_notification("[Plugin: SYNC] Data received ({$plugin_folder})", "info");
|
||||
|
||||
} else {
|
||||
http_response_code(405);
|
||||
echo 'Method Not Allowed';
|
||||
|
||||
@@ -7,6 +7,7 @@ import hashlib
|
||||
import requests
|
||||
import json
|
||||
import sqlite3
|
||||
import base64
|
||||
|
||||
|
||||
# Define the installation path and extend the system path for plugin imports
|
||||
@@ -46,24 +47,66 @@ def main():
|
||||
hub_url = get_setting_value('SYNC_hub_url')
|
||||
node_name = get_setting_value('SYNC_node_name')
|
||||
send_devices = get_setting_value('SYNC_devices')
|
||||
pull_nodes = get_setting_value('SYNC_nodes')
|
||||
|
||||
# variables to determine operation mode
|
||||
is_hub = False
|
||||
is_node = False
|
||||
|
||||
# Check if api_token set
|
||||
if not api_token:
|
||||
mylog('verbose', [f'[{pluginName}] ⚠ ERROR api_token not defined - quitting.'])
|
||||
return -1
|
||||
|
||||
# Get all plugin configurations
|
||||
all_plugins = get_plugins_configs()
|
||||
# check if this is a hub or a node
|
||||
if len(hub_url) > 0 and (send_devices or plugins_to_sync):
|
||||
is_node = True
|
||||
mylog('verbose', [f'[{pluginName}] Mode 1: PUSH (NODE) - This is a NODE as SYNC_hub_url, SYNC_devices or SYNC_plugins are set'])
|
||||
if len(pull_nodes) > 0:
|
||||
is_hub = True
|
||||
mylog('verbose', [f'[{pluginName}] Mode 2: PULL (HUB) - This is a HUB as SYNC_nodes is set'])
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] plugins_to_sync {plugins_to_sync}'])
|
||||
# Mode 1: PUSH/SEND (NODE)
|
||||
if is_node:
|
||||
# PUSHING/SENDING Plugins
|
||||
|
||||
# Get all plugin configurations
|
||||
all_plugins = get_plugins_configs()
|
||||
|
||||
# Plugins processing
|
||||
index = 0
|
||||
for plugin in all_plugins:
|
||||
pref = plugin["unique_prefix"]
|
||||
mylog('verbose', [f'[{pluginName}] plugins_to_sync {plugins_to_sync}'])
|
||||
|
||||
for plugin in all_plugins:
|
||||
pref = plugin["unique_prefix"]
|
||||
|
||||
if pref in plugins_to_sync:
|
||||
index += 1
|
||||
mylog('verbose', [f'[{pluginName}] synching "{pref}" ({index}/{len(plugins_to_sync)})'])
|
||||
index = 0
|
||||
if pref in plugins_to_sync:
|
||||
index += 1
|
||||
mylog('verbose', [f'[{pluginName}] synching "{pref}" ({index}/{len(plugins_to_sync)})'])
|
||||
|
||||
# Construct the file path for the plugin's last_result.log file
|
||||
plugin_folder = plugin["code_name"]
|
||||
file_path = f"{INSTALL_PATH}/front/plugins/{plugin_folder}/last_result.log"
|
||||
# Construct the file path for the plugin's last_result.log file
|
||||
plugin_folder = plugin["code_name"]
|
||||
file_path = f"{INSTALL_PATH}/front/plugins/{plugin_folder}/last_result.log"
|
||||
|
||||
if os.path.exists(file_path):
|
||||
# Read the content of the log file
|
||||
with open(file_path, 'r') as f:
|
||||
file_content = f.read()
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Sending file_content: "{file_content}"'])
|
||||
|
||||
# encrypt and send data to the hub
|
||||
send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url)
|
||||
|
||||
else:
|
||||
mylog('verbose', [f'[{pluginName}] {plugin_folder}/last_result.log not found'])
|
||||
|
||||
|
||||
# PUSHING/SENDING devices
|
||||
if send_devices:
|
||||
|
||||
file_path = f"{INSTALL_PATH}/front/api/table_devices.json"
|
||||
plugin_folder = 'sync'
|
||||
pref = 'SYNC'
|
||||
|
||||
if os.path.exists(file_path):
|
||||
# Read the content of the log file
|
||||
@@ -71,131 +114,147 @@ def main():
|
||||
file_content = f.read()
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Sending file_content: "{file_content}"'])
|
||||
|
||||
# encrypt and send data to the hub
|
||||
send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url)
|
||||
else:
|
||||
mylog('verbose', [f'[{pluginName}] SYNC_hub_url not defined, skipping posting "Devices" data'])
|
||||
else:
|
||||
mylog('verbose', [f'[{pluginName}] SYNC_hub_url not defined, skipping posting "Plugins" and "Devices" data'])
|
||||
|
||||
else:
|
||||
mylog('verbose', [f'[{pluginName}] {plugin_folder}/last_result.log not found'])
|
||||
|
||||
# Devices procesing
|
||||
if send_devices:
|
||||
|
||||
file_path = f"{INSTALL_PATH}/front/api/table_devices.json"
|
||||
plugin_folder = 'sync'
|
||||
pref = 'SYNC'
|
||||
|
||||
if os.path.exists(file_path):
|
||||
# Read the content of the log file
|
||||
with open(file_path, 'r') as f:
|
||||
file_content = f.read()
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Sending file_content: "{file_content}"'])
|
||||
send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url)
|
||||
|
||||
# process any received data for the Device DB table
|
||||
# Create the file path
|
||||
# Mode 2: PULL/GET (HUB)
|
||||
|
||||
# PULLING DEVICES
|
||||
|
||||
file_dir = os.path.join(pluginsPath, 'sync')
|
||||
file_prefix = 'last_result'
|
||||
|
||||
# pull data from nodes if specified
|
||||
if is_hub:
|
||||
for node_url in pull_nodes:
|
||||
response_json = get_data(api_token, node_url)
|
||||
|
||||
# Extract node_name and base64 data
|
||||
node_name = response_json.get('node_name', 'unknown_node')
|
||||
data_base64 = response_json.get('data_base64', '')
|
||||
|
||||
# Decode base64 data
|
||||
decoded_data = base64.b64decode(data_base64)
|
||||
|
||||
# Create log file name using node name
|
||||
log_file_name = f'{file_prefix}.{node_name}.log'
|
||||
|
||||
# Write decoded data to log file
|
||||
with open(os.path.join(file_dir, log_file_name), 'wb') as log_file:
|
||||
log_file.write(decoded_data)
|
||||
|
||||
message = f'[{pluginName}] Device data from node "{node_name}" written to {log_file_name}'
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'info', timeNowTZ())
|
||||
|
||||
|
||||
# Process any received data for the Device DB table
|
||||
# Create the file path
|
||||
|
||||
# Decode files, rename them, and get the list of files
|
||||
files_to_process = decode_and_rename_files(file_dir, file_prefix)
|
||||
|
||||
# Connect to the App database
|
||||
conn = sqlite3.connect(fullDbPath)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Collect all unique dev_MAC values from the JSON files
|
||||
unique_mac_addresses = set()
|
||||
device_data = []
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Devices files to process: "{files_to_process}"'])
|
||||
|
||||
for file_name in files_to_process:
|
||||
|
||||
# only process received .log files, skipping the one logging the progress of this plugin
|
||||
if file_name != 'last_result.log':
|
||||
mylog('verbose', [f'[{pluginName}] Processing: "{file_name}"'])
|
||||
|
||||
# Store e.g. Node_1 from last_result.encoded.Node_1.1.log
|
||||
tmp_SyncHubNodeName = ''
|
||||
if len(file_name.split('.')) > 3:
|
||||
tmp_SyncHubNodeName = file_name.split('.')[2]
|
||||
|
||||
|
||||
file_path = f"{INSTALL_PATH}/front/plugins/sync/{file_name}"
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
for device in data['data']:
|
||||
if device['dev_MAC'] not in unique_mac_addresses:
|
||||
device['dev_SyncHubNodeName'] = tmp_SyncHubNodeName
|
||||
unique_mac_addresses.add(device['dev_MAC'])
|
||||
device_data.append(device)
|
||||
|
||||
|
||||
if len(files_to_process) > 0:
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Mode 3: RECEIVE (HUB) - This is a HUB as received data found'])
|
||||
|
||||
if len(device_data) > 0:
|
||||
# Retrieve existing dev_MAC values from the Devices table
|
||||
placeholders = ', '.join('?' for _ in unique_mac_addresses)
|
||||
cursor.execute(f'SELECT dev_MAC FROM Devices WHERE dev_MAC IN ({placeholders})', tuple(unique_mac_addresses))
|
||||
existing_mac_addresses = set(row[0] for row in cursor.fetchall())
|
||||
|
||||
# Connect to the App database
|
||||
conn = sqlite3.connect(fullDbPath)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# insert devices into the lats_result.log to manage state
|
||||
for device in device_data:
|
||||
if device['dev_PresentLastScan'] == 1:
|
||||
plugin_objects.add_object(
|
||||
primaryId = device['dev_MAC'],
|
||||
secondaryId = device['dev_LastIP'],
|
||||
watched1 = device['dev_Name'],
|
||||
watched2 = device['dev_Vendor'],
|
||||
watched3 = device['dev_SyncHubNodeName'],
|
||||
watched4 = device['dev_GUID'],
|
||||
extra = '',
|
||||
foreignKey = device['dev_GUID'])
|
||||
# Collect all unique dev_MAC values from the JSON files
|
||||
unique_mac_addresses = set()
|
||||
device_data = []
|
||||
|
||||
# Filter out existing devices
|
||||
new_devices = [device for device in device_data if device['dev_MAC'] not in existing_mac_addresses]
|
||||
mylog('verbose', [f'[{pluginName}] Devices files to process: "{files_to_process}"'])
|
||||
|
||||
# Remove 'rowid' key if it exists
|
||||
for device in new_devices:
|
||||
device.pop('rowid', None)
|
||||
for file_name in files_to_process:
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] All devices: "{len(device_data)}"'])
|
||||
mylog('verbose', [f'[{pluginName}] New devices: "{len(new_devices)}"'])
|
||||
# only process received .log files, skipping the one logging the progress of this plugin
|
||||
if file_name != 'last_result.log':
|
||||
mylog('verbose', [f'[{pluginName}] Processing: "{file_name}"'])
|
||||
|
||||
# Prepare the insert statement
|
||||
if new_devices:
|
||||
# Store e.g. Node_1 from last_result.encoded.Node_1.1.log
|
||||
tmp_SyncHubNodeName = ''
|
||||
if len(file_name.split('.')) > 3:
|
||||
tmp_SyncHubNodeName = file_name.split('.')[2]
|
||||
|
||||
columns = ', '.join(k for k in new_devices[0].keys() if k != 'rowid')
|
||||
placeholders = ', '.join('?' for k in new_devices[0] if k != 'rowid')
|
||||
sql = f'INSERT INTO Devices ({columns}) VALUES ({placeholders})'
|
||||
|
||||
# Extract values for the new devices
|
||||
values = [tuple(device.values()) for device in new_devices]
|
||||
file_path = f"{INSTALL_PATH}/front/plugins/sync/{file_name}"
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
for device in data['data']:
|
||||
if device['dev_MAC'] not in unique_mac_addresses:
|
||||
device['dev_SyncHubNodeName'] = tmp_SyncHubNodeName
|
||||
unique_mac_addresses.add(device['dev_MAC'])
|
||||
device_data.append(device)
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Inserting Devices SQL : "{sql}"'])
|
||||
mylog('verbose', [f'[{pluginName}] Inserting Devices VALUES: "{values}"'])
|
||||
if len(device_data) > 0:
|
||||
# Retrieve existing dev_MAC values from the Devices table
|
||||
placeholders = ', '.join('?' for _ in unique_mac_addresses)
|
||||
cursor.execute(f'SELECT dev_MAC FROM Devices WHERE dev_MAC IN ({placeholders})', tuple(unique_mac_addresses))
|
||||
existing_mac_addresses = set(row[0] for row in cursor.fetchall())
|
||||
|
||||
|
||||
# Use executemany for batch insertion
|
||||
cursor.executemany(sql, values)
|
||||
# insert devices into the lats_result.log to manage state
|
||||
for device in device_data:
|
||||
if device['dev_PresentLastScan'] == 1:
|
||||
plugin_objects.add_object(
|
||||
primaryId = device['dev_MAC'],
|
||||
secondaryId = device['dev_LastIP'],
|
||||
watched1 = device['dev_Name'],
|
||||
watched2 = device['dev_Vendor'],
|
||||
watched3 = device['dev_SyncHubNodeName'],
|
||||
watched4 = device['dev_GUID'],
|
||||
extra = '',
|
||||
foreignKey = device['dev_GUID'])
|
||||
|
||||
message = f'[{pluginName}] Inserted "{len(new_devices)}" new devices'
|
||||
# Filter out existing devices
|
||||
new_devices = [device for device in device_data if device['dev_MAC'] not in existing_mac_addresses]
|
||||
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'info', timeNowTZ())
|
||||
# Remove 'rowid' key if it exists
|
||||
for device in new_devices:
|
||||
device.pop('rowid', None)
|
||||
|
||||
# Commit and close the connection
|
||||
conn.commit()
|
||||
conn.close()
|
||||
mylog('verbose', [f'[{pluginName}] All devices: "{len(device_data)}"'])
|
||||
mylog('verbose', [f'[{pluginName}] New devices: "{len(new_devices)}"'])
|
||||
|
||||
# log result
|
||||
plugin_objects.write_result_file()
|
||||
# Prepare the insert statement
|
||||
if new_devices:
|
||||
|
||||
columns = ', '.join(k for k in new_devices[0].keys() if k != 'rowid')
|
||||
placeholders = ', '.join('?' for k in new_devices[0] if k != 'rowid')
|
||||
sql = f'INSERT INTO Devices ({columns}) VALUES ({placeholders})'
|
||||
|
||||
# Extract values for the new devices
|
||||
values = [tuple(device.values()) for device in new_devices]
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Inserting Devices SQL : "{sql}"'])
|
||||
mylog('verbose', [f'[{pluginName}] Inserting Devices VALUES: "{values}"'])
|
||||
|
||||
# Use executemany for batch insertion
|
||||
cursor.executemany(sql, values)
|
||||
|
||||
message = f'[{pluginName}] Inserted "{len(new_devices)}" new devices'
|
||||
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'info', timeNowTZ())
|
||||
|
||||
# Commit and close the connection
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
# log result
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# send data to the HUB
|
||||
def send_data(api_token, file_content, encryption_key, plugin_folder, node_name, pref, hub_url):
|
||||
# Encrypt the log data using the encryption_key
|
||||
encrypted_data = encrypt_data(file_content, encryption_key)
|
||||
@@ -223,6 +282,36 @@ def send_data(api_token, file_content, encryption_key, plugin_folder, node_name,
|
||||
message = f'[{pluginName}] Failed to send data for "{plugin_folder}" (Status code: {response.status_code})'
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'alert', timeNowTZ())
|
||||
|
||||
# get data from the nodes to the HUB
|
||||
def get_data(api_token, node_url):
|
||||
mylog('verbose', [f'[{pluginName}] Getting data from node: "{node_url}"'])
|
||||
|
||||
# Set the authorization header with the API token
|
||||
headers = {'Authorization': f'Bearer {api_token}'}
|
||||
api_endpoint = f"{node_url}/plugins/sync/hub.php"
|
||||
response = requests.get(api_endpoint, headers=headers)
|
||||
|
||||
# mylog('verbose', [f'[{pluginName}] response: "{response}"'])
|
||||
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
# Parse JSON response
|
||||
response_json = response.json()
|
||||
|
||||
return response_json
|
||||
|
||||
except json.JSONDecodeError:
|
||||
message = f'[{pluginName}] Failed to parse JSON response from "{node_url}"'
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'alert', timeNowTZ())
|
||||
return ""
|
||||
|
||||
else:
|
||||
message = f'[{pluginName}] Failed to send data for "{node_url}" (Status code: {response.status_code})'
|
||||
mylog('verbose', [message])
|
||||
write_notification(message, 'alert', timeNowTZ())
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,367 @@
|
||||
],
|
||||
"params": [],
|
||||
"settings": [
|
||||
{
|
||||
"function": "NOT_RANDOM_MAC",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [
|
||||
{ "placeholder": "Enter value" },
|
||||
{ "suffix": "_in" },
|
||||
{ "cssClasses": "col-sm-10" },
|
||||
{ "prefillValue": "null" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this,false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "multiple": "true" },
|
||||
{ "readonly": "true" },
|
||||
{ "editable": "true" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [],
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "ICONS",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [
|
||||
{ "placeholder": "Enter value" },
|
||||
{ "suffix": "_in" },
|
||||
{ "cssClasses": "col-sm-10" },
|
||||
{ "prefillValue": "null" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": ["_in"] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-12" },
|
||||
{ "onClick": "addList(this,false)" },
|
||||
{ "getStringKey": "Gen_Add" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementHasInputValue": 1,
|
||||
"elementOptions": [
|
||||
{ "multiple": "true" },
|
||||
{ "readonly": "true" },
|
||||
{ "editable": "true" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeAllOptions(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-6" },
|
||||
{ "onClick": "removeFromList(this)" },
|
||||
{ "getStringKey": "Gen_Remove_Last" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [
|
||||
"PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4=",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==",
|
||||
"PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4=",
|
||||
"PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4="
|
||||
],
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "REFRESH",
|
||||
"type": {
|
||||
"dataType": "integer",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "number" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": 0,
|
||||
"options": [],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "DEV_SECTIONS",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [],
|
||||
"options": ["Tile Cards", "Device Presence"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "PRESENCE",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": ["online", "offline", "archived"],
|
||||
"options": ["online", "offline", "archived"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "MY_DEVICES",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": ["online", "offline", "archived", "new", "down"],
|
||||
"options": ["online", "offline", "archived", "new", "down"],
|
||||
"localized": [],
|
||||
"name": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"string": "_GLOBAL_LANG_FILES_"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "device_columns",
|
||||
"type": {
|
||||
"dataType": "array",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "select",
|
||||
"elementOptions": [{ "multiple": "true", "ordeable": "true" }],
|
||||
"transformers": ["getString"]
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "selectAll(this)" },
|
||||
{ "getStringKey": "Gen_Add_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "unselectAll(this)" },
|
||||
{ "getStringKey": "Gen_Remove_All" }
|
||||
],
|
||||
"transformers": []
|
||||
},
|
||||
{
|
||||
"elementType": "button",
|
||||
"elementOptions": [
|
||||
{ "sourceSuffixes": [] },
|
||||
{ "separator": "" },
|
||||
{ "cssClasses": "col-xs-4" },
|
||||
{ "onClick": "selectChange(this)" },
|
||||
{ "getStringKey": "Gen_Change" }
|
||||
],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"maxLength": 50,
|
||||
"default_value": [
|
||||
"Device_TableHead_Icon",
|
||||
"Device_TableHead_Name",
|
||||
"Device_TableHead_Type",
|
||||
"Device_TableHead_LastIP",
|
||||
"Device_TableHead_Status",
|
||||
"Device_TableHead_MAC_full"
|
||||
],
|
||||
"options": [
|
||||
"Device_TableHead_Name",
|
||||
"Device_TableHead_Owner",
|
||||
"Device_TableHead_Type",
|
||||
"Device_TableHead_Icon",
|
||||
"Device_TableHead_Favorite",
|
||||
"Device_TableHead_Group",
|
||||
"Device_TableHead_FirstSession",
|
||||
"Device_TableHead_LastSession",
|
||||
"Device_TableHead_LastIP",
|
||||
"Device_TableHead_MAC",
|
||||
"Device_TableHead_Status",
|
||||
"Device_TableHead_MAC_full",
|
||||
"Device_TableHead_LastIPOrder",
|
||||
"Device_TableHead_Rowid",
|
||||
"Device_TableHead_Parent_MAC",
|
||||
"Device_TableHead_Connected_Devices",
|
||||
"Device_TableHead_Location",
|
||||
"Device_TableHead_Vendor",
|
||||
"Device_TableHead_Port",
|
||||
"Device_TableHead_GUID",
|
||||
"Device_TableHead_SyncHubNodeName",
|
||||
"Device_TableHead_NetworkSite",
|
||||
"Device_TableHead_SSID"
|
||||
],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Device Columns"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Columns and their order that are shown on the Devices page. Drag and drop the order of columns, click <code>x</code> to remove columns. You can also click into the field to selectivelly add fields."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "shown_cards",
|
||||
"type": {
|
||||
@@ -67,7 +428,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Which tiles to show on teh top of the Devices page."
|
||||
"string": "Which tiles to show on the top of the Devices page."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -98,6 +459,34 @@
|
||||
"string": "Hide Device tiles with zero results."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "dark_mode",
|
||||
"type": {
|
||||
"dataType": "boolean",
|
||||
"elements": [
|
||||
{
|
||||
"elementType": "input",
|
||||
"elementOptions": [{ "type": "checkbox" }],
|
||||
"transformers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_value": false,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Dark mode"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Enable dark mode."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,28 +25,12 @@
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "<i class=\"fa-solid fa-binoculars\"></i>"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "<i class=\"fa-solid fa-binoculars\"></i>"
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string": "<i class=\"fa-solid fa-binoculars\"></i>"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "This plugin is to import undiscoverable devices from a file."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string": "Este complemento es para importar dispositivos no detectables desde un archivo."
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string": "Ein Plugin zum Importieren von nicht erkennbaren Geräten aus einer Datei."
|
||||
"string": "This plugin is to import undiscoverable devices from a file. Only ASCII characters are supported."
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
|
||||
@@ -42,7 +42,7 @@ def main():
|
||||
fake_mac = string_to_mac_hash(fake_dev)
|
||||
|
||||
plugin_objects.add_object(
|
||||
primaryId=fake_dev, # MAC (Device Name)
|
||||
primaryId=fake_mac, # MAC (Device Name)
|
||||
secondaryId="0.0.0.0", # IP Address (always 0.0.0.0)
|
||||
watched1=fake_dev, # Device Name
|
||||
watched2="",
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
// Function to update the displayed data and timestamp based on the selected format and index
|
||||
function updateData(format, index) {
|
||||
// Fetch data from the API endpoint
|
||||
fetch('/api/table_notifications.json?nocache=' + Date.now())
|
||||
fetch('api/table_notifications.json?nocache=' + Date.now())
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (index < 0) {
|
||||
@@ -163,7 +163,7 @@
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('guid')) {
|
||||
const guid = urlParams.get('guid');
|
||||
fetch('/api/table_notifications.json')
|
||||
fetch('api/table_notifications.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const index = findIndexByGUID(data.data, guid);
|
||||
|
||||
@@ -378,6 +378,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
|
||||
const valIn = set['Value'];
|
||||
const codeName = set['Code_Name'];
|
||||
const overriddenByEnv = set['OverriddenByEnv'] == 1;
|
||||
const setType = set['Type'];
|
||||
const isMetadata = codeName.includes('__metadata');
|
||||
// is this isn't a metadata entry, get corresponding metadata object from the dummy setting
|
||||
@@ -416,11 +417,11 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
<div class="table_cell setting_description">
|
||||
${getString(codeName + '_description', set['Description'])}
|
||||
</div>
|
||||
<div class="table_cell setting_input input-group col-sm-12">
|
||||
<div class="table_cell input-group setting_input ${overriddenByEnv ? "setting_overriden_by_env" : ""} input-group col-sm-12">
|
||||
`;
|
||||
|
||||
// OVERRIDE
|
||||
// surface settings override functionality if the setting is a template that can be overriden with user defined values
|
||||
// surface settings override functionality if the setting is a template that can be overridden with user defined values
|
||||
// if the setting is a json of the correct structure, handle like a template setting
|
||||
|
||||
let overrideHtml = "";
|
||||
@@ -428,7 +429,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
//pre-check if this is a json object that needs value extraction
|
||||
|
||||
let overridable = false; // indicates if the setting is overridable
|
||||
let override = false; // If the setting is set to be overriden by the user or by default
|
||||
let override = false; // If the setting is set to be overridden by the user or by default
|
||||
let readonly = ""; // helper variable to make text input readonly
|
||||
let disabled = ""; // helper variable to make checkbox input readonly
|
||||
|
||||
@@ -460,7 +461,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
|
||||
// INPUT
|
||||
|
||||
console.log(codeName);
|
||||
// console.log(codeName);
|
||||
|
||||
// Parse the setType JSON string into an object
|
||||
let inputHtml = '';
|
||||
@@ -476,6 +477,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
inputType,
|
||||
readOnly,
|
||||
isMultiSelect,
|
||||
isOrdeable,
|
||||
cssClasses,
|
||||
placeholder,
|
||||
suffix,
|
||||
@@ -484,7 +486,10 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
editable,
|
||||
valRes,
|
||||
getStringKey,
|
||||
onClick
|
||||
onClick,
|
||||
onChange,
|
||||
customParams,
|
||||
customId
|
||||
} = handleElementOptions(codeName, elementOptions, transformers, valIn);
|
||||
|
||||
// override
|
||||
@@ -494,8 +499,18 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
switch (elementType) {
|
||||
case 'select':
|
||||
let multi = isMultiSelect ? "multiple" : "";
|
||||
let addCss = isOrdeable ? "select2 select2-hidden-accessible" : "";
|
||||
|
||||
inputHtml += `<select onChange="settingsChanged()" my-data-type="${dataType}" my-editable="${editable}" class="form-control" name="${codeName}" id="${codeName}" ${multi}>
|
||||
|
||||
inputHtml += `<select onChange="settingsChanged();${onChange}"
|
||||
my-data-type="${dataType}"
|
||||
my-editable="${editable}"
|
||||
class="form-control ${addCss}"
|
||||
name="${codeName}"
|
||||
id="${codeName}"
|
||||
my-customparams="${customParams}"
|
||||
my-customid="${customId}"
|
||||
${multi}>
|
||||
<option value="" id="${codeName + "_temp_"}"></option>
|
||||
</select>`;
|
||||
|
||||
@@ -510,8 +525,10 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
inputHtml += `
|
||||
<input
|
||||
class="${inputClass} ${cssClasses}"
|
||||
onChange="settingsChanged()"
|
||||
onChange="settingsChanged();${onChange}"
|
||||
my-data-type="${dataType}"
|
||||
my-customparams="${customParams}"
|
||||
my-customid="${customId}"
|
||||
id="${codeName}${suffix}"
|
||||
type="${inputType}"
|
||||
value="${val}"
|
||||
@@ -526,6 +543,8 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
inputHtml += `
|
||||
<button
|
||||
class="btn btn-primary ${cssClasses}"
|
||||
my-customparams="${customParams}"
|
||||
my-customid="${customId}"
|
||||
my-input-from="${sourceIds}"
|
||||
my-input-to="${codeName}"
|
||||
onclick="${onClick}">
|
||||
@@ -536,12 +555,25 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
inputHtml += `
|
||||
<textarea
|
||||
class="form-control input"
|
||||
my-customparams="${customParams}"
|
||||
my-customid="${customId}"
|
||||
my-data-type="${dataType}"
|
||||
id="${codeName}"
|
||||
${readOnly}>
|
||||
${val}
|
||||
</textarea>`;
|
||||
break;
|
||||
case 'span':
|
||||
inputHtml += `
|
||||
<span
|
||||
class="${cssClasses}"
|
||||
my-data-type="${dataType}"
|
||||
my-customparams="${customParams}"
|
||||
my-customid="${customId}"
|
||||
>
|
||||
${getString(getStringKey)}
|
||||
</span>`;
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(`🟥Unknown element type: ${elementType}`);
|
||||
@@ -549,7 +581,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
});
|
||||
|
||||
// EVENTS
|
||||
// process events (e.g. run ascan, or test a notification) if associated with the setting
|
||||
// process events (e.g. run a scan, or test a notification) if associated with the setting
|
||||
let eventsHtml = "";
|
||||
|
||||
const eventsList = createArray(set['Events']);
|
||||
@@ -588,6 +620,8 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
}, 50);
|
||||
|
||||
setupSmoothScrolling()
|
||||
// try to initialize select2
|
||||
initSelect2()
|
||||
hideSpinner()
|
||||
|
||||
}
|
||||
@@ -635,16 +669,26 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
// console.log(setTypeObject);
|
||||
|
||||
const dataType = setTypeObject.dataType;
|
||||
// const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1]; //🔽
|
||||
|
||||
|
||||
// get the element with the input value(s)
|
||||
const elementsWithInputValue = setTypeObject.elements.filter(element => element.elementHasInputValue === 1);
|
||||
let elements = setTypeObject.elements.filter(element => element.elementHasInputValue === 1);
|
||||
|
||||
const { elementType, elementOptions = [], transformers = [] } = elementsWithInputValue;
|
||||
// if none found, take last
|
||||
if(elements.length == 0)
|
||||
{
|
||||
elementWithInputValue = setTypeObject.elements[setTypeObject.elements.length - 1]
|
||||
} else
|
||||
{
|
||||
elementWithInputValue = elements[0]
|
||||
}
|
||||
|
||||
const { elementType, elementOptions = [], transformers = [] } = elementWithInputValue;
|
||||
const {
|
||||
inputType,
|
||||
readOnly,
|
||||
isMultiSelect,
|
||||
isOrdeable,
|
||||
cssClasses,
|
||||
placeholder,
|
||||
suffix,
|
||||
@@ -653,38 +697,51 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
editable,
|
||||
valRes,
|
||||
getStringKey,
|
||||
onClick
|
||||
onClick,
|
||||
onChange,
|
||||
customParams,
|
||||
customId
|
||||
} = handleElementOptions('none', elementOptions, transformers, val = "");
|
||||
|
||||
let value;
|
||||
|
||||
if (dataType === "string" ||
|
||||
(dataType === "integer" && (inputType === "number" || inputType === "text"))) {
|
||||
|
||||
|
||||
value = $('#' + setCodeName).val();
|
||||
value = applyTransformers(value, transformers);
|
||||
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (inputType === 'checkbox') {
|
||||
} else if (dataType === 'boolean') {
|
||||
|
||||
value = $(`#${setCodeName}`).is(':checked') ? 1 : 0;
|
||||
value = applyTransformers(value, transformers);
|
||||
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (dataType === "array" ) {
|
||||
|
||||
// make sure to collect all if set as "editable" or selected only otherwise
|
||||
$(`#${setCodeName}`).attr("my-editable") == "true" ? additionalSelector = "" : additionalSelector = ":selected"
|
||||
|
||||
const temps = [];
|
||||
$(`#${setCodeName} option${additionalSelector}`).each(function() {
|
||||
const vl = $(this).val();
|
||||
if (vl !== '') {
|
||||
temps.push(applyTransformers(vl, transformers));
|
||||
}
|
||||
});
|
||||
let temps = [];
|
||||
|
||||
if(isOrdeable)
|
||||
{
|
||||
temps = $(`#${setCodeName}`).val()
|
||||
} else
|
||||
{
|
||||
// make sure to collect all if set as "editable" or selected only otherwise
|
||||
$(`#${setCodeName}`).attr("my-editable") == "true" ? additionalSelector = "" : additionalSelector = ":selected";
|
||||
|
||||
$(`#${setCodeName} option${additionalSelector}`).each(function() {
|
||||
const vl = $(this).val();
|
||||
if (vl !== '') {
|
||||
temps.push(applyTransformers(vl, transformers));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
value = JSON.stringify(temps);
|
||||
|
||||
settingsArray.push([prefix, setCodeName, dataType, value]);
|
||||
|
||||
} else if (dataType === "json") {
|
||||
@@ -780,34 +837,35 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
|
||||
setTimeout("handleLoadingDialog()", 1000);
|
||||
|
||||
} else
|
||||
{
|
||||
// check if the app is initialized and hide the spinner
|
||||
if(isAppInitialized())
|
||||
{
|
||||
// init page
|
||||
getData()
|
||||
|
||||
// reload page if outdated information might be displayed
|
||||
if(secondsSincePageLoad() > 5)
|
||||
{
|
||||
clearCache()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// reload the page if not initialized to give time the background tasks to finish
|
||||
setTimeout(() => {
|
||||
|
||||
window.location.reload()
|
||||
|
||||
}, 3000);
|
||||
}
|
||||
{
|
||||
checkInitialization();
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('lastImportedTime').innerHTML = humanReadable;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
function checkInitialization() {
|
||||
if (isAppInitialized()) {
|
||||
// App is initialized, hide spinner and proceed with initialization
|
||||
console.log("App initialized, proceeding...");
|
||||
getData();
|
||||
|
||||
// Reload page if outdated information might be displayed
|
||||
if (secondsSincePageLoad() > 10) {
|
||||
console.log("App outdated, reloading...");
|
||||
clearCache();
|
||||
}
|
||||
} else {
|
||||
console.log("App not initialized, checking again in 1s...");
|
||||
|
||||
// Check again after a delay
|
||||
setTimeout(checkInitialization, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
showSpinner()
|
||||
|
||||
@@ -60,7 +60,7 @@ require 'php/templates/header.php';
|
||||
<script>
|
||||
function fetchData(callback) {
|
||||
$.ajax({
|
||||
url: '/api/user_notifications.json?nocache=' + Date.now(),
|
||||
url: 'api/user_notifications.json?nocache=' + Date.now(),
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
|
||||
@@ -15,6 +15,7 @@ pluginsPath = applicationPath + '/front/plugins'
|
||||
logPath = applicationPath + '/front/log'
|
||||
apiPath = applicationPath + '/front/api/'
|
||||
reportTemplatesPath = applicationPath + '/front/report_templates/'
|
||||
fullConfFolder = applicationPath + '/config'
|
||||
fullConfPath = applicationPath + confPath
|
||||
fullDbPath = applicationPath + dbPath
|
||||
vendorsPath = '/usr/share/arp-scan/ieee-oui.txt'
|
||||
|
||||
@@ -213,15 +213,16 @@ class DB():
|
||||
self.sql.execute(""" DROP TABLE IF EXISTS Settings;""")
|
||||
self.sql.execute("""
|
||||
CREATE TABLE "Settings" (
|
||||
"Code_Name" TEXT,
|
||||
"Display_Name" TEXT,
|
||||
"Description" TEXT,
|
||||
"Type" TEXT,
|
||||
"Options" TEXT,
|
||||
"RegEx" TEXT,
|
||||
"Value" TEXT,
|
||||
"Group" TEXT,
|
||||
"Events" TEXT
|
||||
"Code_Name" TEXT,
|
||||
"Display_Name" TEXT,
|
||||
"Description" TEXT,
|
||||
"Type" TEXT,
|
||||
"Options" TEXT,
|
||||
"RegEx" TEXT,
|
||||
"Group" TEXT,
|
||||
"Value" TEXT,
|
||||
"Events" TEXT,
|
||||
"OverriddenByEnv" INTEGER
|
||||
);
|
||||
""")
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import subprocess
|
||||
import conf
|
||||
import os
|
||||
import re
|
||||
from helper import timeNowTZ, get_setting, get_setting_value, list_to_where, resolve_device_name_dig, resolve_device_name_pholus, get_device_name_nbtlookup, get_device_name_nslookup, check_IP_format
|
||||
from helper import timeNowTZ, get_setting, get_setting_value, list_to_where, resolve_device_name_dig, resolve_device_name_pholus, get_device_name_nbtlookup, get_device_name_nslookup, check_IP_format, sanitize_SQL_input
|
||||
from logger import mylog, print_log
|
||||
from const import vendorsPath, vendorsPathNewest, sql_generateGuid
|
||||
|
||||
@@ -192,12 +192,12 @@ def create_new_devices (db):
|
||||
{get_setting_value('NEWDEV_dev_NewDevice')},
|
||||
{get_setting_value('NEWDEV_dev_SkipRepeated')},
|
||||
{get_setting_value('NEWDEV_dev_ScanCycle')},
|
||||
'{get_setting_value('NEWDEV_dev_Owner')}',
|
||||
'{sanitize_SQL_input(get_setting_value('NEWDEV_dev_Owner'))}',
|
||||
{get_setting_value('NEWDEV_dev_Favorite')},
|
||||
'{get_setting_value('NEWDEV_dev_Group')}',
|
||||
'{get_setting_value('NEWDEV_dev_Comments')}',
|
||||
'{sanitize_SQL_input(get_setting_value('NEWDEV_dev_Group'))}',
|
||||
'{sanitize_SQL_input(get_setting_value('NEWDEV_dev_Comments'))}',
|
||||
{get_setting_value('NEWDEV_dev_LogEvents')},
|
||||
'{get_setting_value('NEWDEV_dev_Location')}'"""
|
||||
'{sanitize_SQL_input(get_setting_value('NEWDEV_dev_Location'))}'"""
|
||||
|
||||
# Fetch data from CurrentScan
|
||||
current_scan_data = sql.execute("SELECT cur_MAC, cur_Name, cur_Vendor, cur_IP, cur_SyncHubNodeName, cur_NetworkNodeMAC, cur_PORT, cur_NetworkSite, cur_SSID, cur_Type FROM CurrentScan").fetchall()
|
||||
@@ -210,6 +210,7 @@ def create_new_devices (db):
|
||||
cur_Type = cur_Type.strip() if cur_Type else get_setting_value("NEWDEV_dev_DeviceType")
|
||||
cur_NetworkNodeMAC = cur_NetworkNodeMAC.strip() if cur_NetworkNodeMAC else ''
|
||||
cur_NetworkNodeMAC = cur_NetworkNodeMAC if cur_NetworkNodeMAC and cur_MAC != "Internet" else (get_setting_value("NEWDEV_dev_Network_Node_MAC_ADDR") if cur_MAC != "Internet" else "null")
|
||||
cur_SyncHubNodeName = cur_SyncHubNodeName if cur_SyncHubNodeName and cur_SyncHubNodeName != "null" else (get_setting_value("SYNC_node_name"))
|
||||
|
||||
# Preparing the individual insert statement
|
||||
sqlQuery = f"""INSERT OR IGNORE INTO Devices
|
||||
@@ -231,19 +232,19 @@ def create_new_devices (db):
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
'{cur_MAC}',
|
||||
'{cur_Name}',
|
||||
'{cur_Vendor}',
|
||||
'{cur_IP}',
|
||||
'{sanitize_SQL_input(cur_MAC)}',
|
||||
'{sanitize_SQL_input(cur_Name)}',
|
||||
'{sanitize_SQL_input(cur_Vendor)}',
|
||||
'{sanitize_SQL_input(cur_IP)}',
|
||||
?,
|
||||
?,
|
||||
'{cur_SyncHubNodeName}',
|
||||
'{sanitize_SQL_input(cur_SyncHubNodeName)}',
|
||||
{sql_generateGuid},
|
||||
'{cur_NetworkNodeMAC}',
|
||||
'{cur_PORT}',
|
||||
'{cur_NetworkSite}',
|
||||
'{cur_SSID}',
|
||||
'{cur_Type}',
|
||||
'{sanitize_SQL_input(cur_NetworkNodeMAC)}',
|
||||
'{sanitize_SQL_input(cur_PORT)}',
|
||||
'{sanitize_SQL_input(cur_NetworkSite)}',
|
||||
'{sanitize_SQL_input(cur_SSID)}',
|
||||
'{sanitize_SQL_input(cur_Type)}',
|
||||
{newDevDefaults}
|
||||
)"""
|
||||
|
||||
@@ -637,8 +638,8 @@ icons = {
|
||||
def guess_icon(vendor, mac, ip, name, default):
|
||||
result = default
|
||||
mac = mac.upper()
|
||||
vendor = vendor.lower()
|
||||
name = name.lower()
|
||||
vendor = vendor.lower() if vendor else "unknown"
|
||||
name = name.lower() if name else "(unknown)"
|
||||
|
||||
# Guess icon based on vendor
|
||||
if any(brand in vendor for brand in {"samsung", "motorola"}):
|
||||
@@ -693,8 +694,8 @@ def guess_icon(vendor, mac, ip, name, default):
|
||||
def guess_type(vendor, mac, ip, name, default):
|
||||
result = default
|
||||
mac = mac.upper()
|
||||
vendor = vendor.lower()
|
||||
name = name.lower()
|
||||
vendor = vendor.lower() if vendor else "unknown"
|
||||
name = name.lower() if name else "(unknown)"
|
||||
|
||||
# Guess icon based on vendor
|
||||
if any(brand in vendor for brand in {"samsung", "motorola"}):
|
||||
|
||||
@@ -319,7 +319,7 @@ def get_setting_value(key):
|
||||
set_type = 'Error: Not handled'
|
||||
set_value = 'Error: Not handled'
|
||||
|
||||
set_value = setting["Value"] # Setting value (Value (upper case) = user overriden default_value)
|
||||
set_value = setting["Value"] # Setting value (Value (upper case) = user overridden default_value)
|
||||
set_type = setting["Type"] # Setting type # lower case "type" - default json value vs uppper-case "Type" (= from user defined settings)
|
||||
|
||||
value = setting_value_to_python_type(set_type, set_value)
|
||||
@@ -806,6 +806,13 @@ def sanitize_string(input):
|
||||
return input
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def sanitize_SQL_input(val):
|
||||
if val is None:
|
||||
return ''
|
||||
return val.replace("'", "_")
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def generate_mac_links (html, deviceUrl):
|
||||
|
||||
@@ -909,41 +916,44 @@ def collect_lang_strings(json, pref, stringSqlParams):
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def checkNewVersion():
|
||||
|
||||
mylog('debug', [f"[Version check] Checking if new version available"])
|
||||
|
||||
newVersion = False
|
||||
|
||||
f = open(applicationPath + '/front/buildtimestamp.txt', 'r')
|
||||
buildTimestamp = int(f.read().strip())
|
||||
f.close()
|
||||
|
||||
data = ""
|
||||
with open(applicationPath + '/front/buildtimestamp.txt', 'r') as f:
|
||||
buildTimestamp = int(f.read().strip())
|
||||
|
||||
try:
|
||||
url = requests.get("https://api.github.com/repos/jokob-sk/NetAlertX/releases")
|
||||
text = url.text
|
||||
data = json.loads(text)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
response = requests.get("https://api.github.com/repos/jokob-sk/NetAlertX/releases")
|
||||
response.raise_for_status() # Raise an exception for HTTP errors
|
||||
text = response.text
|
||||
except requests.exceptions.RequestException as e:
|
||||
mylog('minimal', ["[Version check] ⚠ ERROR: Couldn't check for new release."])
|
||||
data = ""
|
||||
return False
|
||||
|
||||
try:
|
||||
data = json.loads(text)
|
||||
except json.JSONDecodeError as e:
|
||||
mylog('minimal', ["[Version check] ⚠ ERROR: Invalid JSON response from GitHub."])
|
||||
return False
|
||||
|
||||
# make sure we received a valid response and not an API rate limit exceeded message
|
||||
if data != "" and len(data) > 0 and isinstance(data, list) and "published_at" in data[0]:
|
||||
|
||||
if data and isinstance(data, list) and "published_at" in data[0]:
|
||||
dateTimeStr = data[0]["published_at"]
|
||||
|
||||
releaseTimestamp = int(datetime.datetime.strptime(dateTimeStr, '%Y-%m-%dT%H:%M:%S%z').timestamp())
|
||||
|
||||
if releaseTimestamp > buildTimestamp + 600:
|
||||
mylog('none', ["[Version check] New version of the container available!"])
|
||||
newVersion = True
|
||||
newVersion = True
|
||||
else:
|
||||
mylog('none', ["[Version check] Running the latest version."])
|
||||
else:
|
||||
mylog('minimal', ["[Version check] ⚠ ERROR: Received unexpected response from GitHub."])
|
||||
|
||||
return newVersion
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def initOrSetParam(db, parID, parValue):
|
||||
sql = db.sql
|
||||
|
||||
@@ -11,13 +11,14 @@ import re
|
||||
|
||||
|
||||
import conf
|
||||
from const import fullConfPath
|
||||
from helper import collect_lang_strings, updateSubnets, initOrSetParam, isJsonObject, updateState, setting_value_to_python_type
|
||||
from const import fullConfPath, applicationPath, fullConfFolder
|
||||
from helper import collect_lang_strings, updateSubnets, initOrSetParam, isJsonObject, updateState, setting_value_to_python_type, timeNowTZ, get_setting_value
|
||||
from logger import mylog
|
||||
from api import update_api
|
||||
from scheduler import schedule_class
|
||||
from plugin import print_plugin_info, run_plugin_scripts
|
||||
from plugin_utils import get_plugins_configs, get_plugin_setting_obj
|
||||
from notification import write_notification
|
||||
|
||||
#===============================================================================
|
||||
# Initialise user defined values
|
||||
@@ -28,7 +29,8 @@ from plugin_utils import get_plugins_configs, get_plugin_setting_obj
|
||||
# Check config dictionary
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None):
|
||||
# managing application settings, ensuring SQL safety for user input, and updating internal configuration lists
|
||||
def ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False, overriddenByEnv=0):
|
||||
if events is None:
|
||||
events = []
|
||||
if setJsonMetadata is None:
|
||||
@@ -40,7 +42,7 @@ def ccd(key, default, config_dir, name, inputtype, options, group, events=None,
|
||||
result = default
|
||||
|
||||
# Use existing value if already supplied, otherwise default value is used
|
||||
if key in config_dir:
|
||||
if forceDefault == False and key in config_dir:
|
||||
result = config_dir[key]
|
||||
|
||||
# Single quotes might break SQL queries, replacing them
|
||||
@@ -48,8 +50,8 @@ def ccd(key, default, config_dir, name, inputtype, options, group, events=None,
|
||||
result = result.replace('\'', "{s-quote}")
|
||||
|
||||
# Create the tuples
|
||||
sql_safe_tuple = (key, name, desc, str(inputtype), options, regex, str(result), group, str(events))
|
||||
settings_tuple = (key, name, desc, inputtype, options, regex, result, group, str(events))
|
||||
sql_safe_tuple = (key, name, desc, str(inputtype), options, regex, str(result), group, str(events), overriddenByEnv)
|
||||
settings_tuple = (key, name, desc, inputtype, options, regex, result, group, str(events), overriddenByEnv)
|
||||
|
||||
# Update or append the tuples in the lists
|
||||
conf.mySettingsSQLsafe = update_or_append(conf.mySettingsSQLsafe, sql_safe_tuple, key)
|
||||
@@ -57,7 +59,7 @@ def ccd(key, default, config_dir, name, inputtype, options, group, events=None,
|
||||
|
||||
# Save metadata in dummy setting if not a metadata key
|
||||
if '__metadata' not in key:
|
||||
metadata_tuple = (f'{key}__metadata', "metadata name", "metadata desc", '{"dataType":"json", "elements": [{"elementType" : "textarea", "elementOptions" : [{"readonly": "true"}] ,"transformers": []}]}', '[]', "", json.dumps(setJsonMetadata), group, '[]')
|
||||
metadata_tuple = (f'{key}__metadata', "metadata name", "metadata desc", '{"dataType":"json", "elements": [{"elementType" : "textarea", "elementOptions" : [{"readonly": "true"}] ,"transformers": []}]}', '[]', "", json.dumps(setJsonMetadata), group, '[]', overriddenByEnv)
|
||||
conf.mySettingsSQLsafe = update_or_append(conf.mySettingsSQLsafe, metadata_tuple, f'{key}__metadata')
|
||||
conf.mySettings = update_or_append(conf.mySettings, metadata_tuple, f'{key}__metadata')
|
||||
|
||||
@@ -69,16 +71,20 @@ def update_or_append(settings_list, item_tuple, key):
|
||||
if settings_list is None:
|
||||
settings_list = []
|
||||
|
||||
# mylog('debug', ['[Import Config] update_or_append debug '])
|
||||
# mylog('debug', ['[Import Config] update_or_append ', settings_list])
|
||||
# mylog('debug', ['[Import Config] update_or_append item_tuple ' , item_tuple])
|
||||
|
||||
for index, item in enumerate(settings_list):
|
||||
if item[0] == key:
|
||||
settings_list[index] = item_tuple
|
||||
mylog('debug', ['[Import Config] FOUND key : ', key])
|
||||
return settings_list
|
||||
mylog('trace', ['[Import Config] OLD TUPLE : ', item])
|
||||
# Keep values marked as "_KEEP_"
|
||||
updated_tuple = tuple(
|
||||
new_val if new_val != "_KEEP_" else old_val
|
||||
for old_val, new_val in zip(item, item_tuple)
|
||||
)
|
||||
mylog('trace', ['[Import Config] NEW TUPLE : ', updated_tuple])
|
||||
settings_list[index] = updated_tuple
|
||||
mylog('trace', ['[Import Config] FOUND key : ', key])
|
||||
return settings_list
|
||||
|
||||
|
||||
settings_list.append(item_tuple)
|
||||
return settings_list
|
||||
|
||||
@@ -139,17 +145,13 @@ def importConfigs (db, all_plugins):
|
||||
conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'http://netalertx/' , c_d, 'NetAlertX URL', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'General')
|
||||
conf.CLEAR_NEW_FLAG = ccd('CLEAR_NEW_FLAG', 0 , c_d, 'Clear new flag', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'General')
|
||||
conf.API_CUSTOM_SQL = ccd('API_CUSTOM_SQL', 'SELECT * FROM Devices WHERE dev_PresentLastScan = 0' , c_d, 'Custom endpoint', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [] ,"transformers": []}]}', '[]', 'General')
|
||||
conf.NETWORK_DEVICE_TYPES = ccd('NETWORK_DEVICE_TYPES', ['AP', 'Gateway', 'Firewall', 'Hypervisor', 'Powerline', 'Switch', 'WLAN', 'PLC', 'Router','USB LAN Adapter', 'USB WIFI Adapter', 'Internet'] , c_d, 'Network device types', '{"dataType":"array","elements":[{"elementType":"input","elementOptions":[{"placeholder":"Entervalue"},{"suffix":"_in"},{"cssClasses":"col-sm-10"},{"prefillValue":"null"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":["_in"]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"addList(this,false)"},{"getStringKey":"Gen_Add"}],"transformers":[]},{"elementType":"select", "elementHasInputValue":1,"elementOptions":[{"multiple":"true"},{"readonly":"true"},{"editable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeAllOptions(this)"},{"getStringKey":"Gen_Remove_All"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeFromList(this)"},{"getStringKey":"Gen_Remove_Last"}],"transformers":[]}]}', '[]', 'General')
|
||||
conf.VERSION = ccd('VERSION', '' , c_d, 'Version', '{"dataType":"string", "elements": [{"elementType" : "input", "elementOptions" : [{ "readonly": "true" }] ,"transformers": []}]}', '', 'General')
|
||||
conf.NETWORK_DEVICE_TYPES = ccd('NETWORK_DEVICE_TYPES', ['AP', 'Gateway', 'Firewall', 'Hypervisor', 'Powerline', 'Switch', 'WLAN', 'PLC', 'Router','USB LAN Adapter', 'USB WIFI Adapter', 'Internet'] , c_d, 'Network device types', '{"dataType":"array","elements":[{"elementType":"input","elementOptions":[{"placeholder":"Enter value"},{"suffix":"_in"},{"cssClasses":"col-sm-10"},{"prefillValue":"null"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":["_in"]},{"separator":""},{"cssClasses":"col-xs-12"},{"onClick":"addList(this,false)"},{"getStringKey":"Gen_Add"}],"transformers":[]},{"elementType":"select", "elementHasInputValue":1,"elementOptions":[{"multiple":"true"},{"readonly":"true"},{"editable":"true"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeAllOptions(this)"},{"getStringKey":"Gen_Remove_All"}],"transformers":[]},{"elementType":"button","elementOptions":[{"sourceSuffixes":[]},{"separator":""},{"cssClasses":"col-xs-6"},{"onClick":"removeFromList(this)"},{"getStringKey":"Gen_Remove_Last"}],"transformers":[]}]}', '[]', 'General')
|
||||
|
||||
# UI
|
||||
conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian (it_it)', 'Portuguese (pt_br)', 'Polish (pl_pl)', 'Turkish (tr_tr)', 'Chinese (zh_cn)' ]", 'UI')
|
||||
conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "suffix": "_in" },{ "cssClasses": "col-sm-10" },{ "prefillValue": "null" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": ["_in"] },{ "separator": "" },{ "cssClasses": "col-xs-12" },{ "onClick": "addList(this, false)" },{ "getStringKey": "Gen_Add" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeAllOptions(this)" },{ "getStringKey": "Gen_Remove_All" }],"transformers": []},{"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeFromList(this)" },{ "getStringKey": "Gen_Remove_Last" }],"transformers": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_ICONS = ccd('UI_ICONS', ['PGkgY2xhc3M9J2ZhIGZhLXdpZmknPjwvaT4=', 'PGkgY2xhc3M9ImZhIGZhLWNvbXB1dGVyIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWV0aGVybmV0Ij48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWdhbWVwYWQiPjwvaT4', 'PGkgY2xhc3M9ImZhIGZhLWdsb2JlIj48L2k+', 'PGkgY2xhc3M9ImZhIGZhLWxhcHRvcCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLWxpZ2h0YnVsYiI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXNoaWVsZCI+PC9pPg==', 'PGkgY2xhc3M9ImZhIGZhLXdpZmkiPjwvaT4', 'PGkgY2xhc3M9J2ZhIGZhLWdhbWVwYWQnPjwvaT4'] , c_d, 'Icons', '{"dataType": "array","elements": [ {"elementType": "input","elementOptions": [{ "placeholder": "Enter value" },{ "suffix": "_in" },{ "cssClasses": "col-sm-10" },{ "prefillValue": "null" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": ["_in"] },{ "separator": "" },{ "cssClasses": "col-xs-12" },{ "onClick": "addList(this, false)" },{ "getStringKey": "Gen_Add" }],"transformers": [] }, {"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeAllOptions(this)" },{ "getStringKey": "Gen_Remove_All" }],"transformers": []},{"elementType": "button","elementOptions": [{ "sourceSuffixes": [] },{ "separator": "" },{ "cssClasses": "col-xs-6" },{ "onClick": "removeFromList(this)" },{ "getStringKey": "Gen_Remove_Last" }],"transformers": []}, {"elementType": "select","elementOptions": [{ "multiple": "true" },{ "readonly": "true" },{ "editable": "true" }],"transformers": [] }]}', "[]", 'UI')
|
||||
conf.UI_REFRESH = ccd('UI_REFRESH', 0 , c_d, 'Refresh interval', '{"dataType":"integer", "elements": [{"elementType" : "input", "elementOptions" : [{"type": "number"}] ,"transformers": []}]}', "[]", 'UI')
|
||||
conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['Tile Cards', 'Device Presence']", 'UI')
|
||||
conf.UI_PRESENCE = ccd('UI_PRESENCE', ['online', 'offline', 'archived'] , c_d, 'Include in presence', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['online', 'offline', 'archived']", 'UI')
|
||||
conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', "['online', 'offline', 'archived', 'new', 'down']", 'UI')
|
||||
conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', '{"dataType":"string", "elements": [{"elementType" : "select", "elementOptions" : [] ,"transformers": []}]}', "['English', 'French', 'German', 'Norwegian', 'Russian', 'Spanish', 'Italian (it_it)', 'Portuguese (pt_br)', 'Polish (pl_pl)', 'Turkish (tr_tr)', 'Chinese (zh_cn)', 'Czech (cs_cz)' ]", 'UI')
|
||||
|
||||
# Init timezone in case it changed
|
||||
conf.tz = timezone(conf.TIMEZONE)
|
||||
@@ -285,8 +287,7 @@ def importConfigs (db, all_plugins):
|
||||
for plugin in all_plugins:
|
||||
pref = plugin["unique_prefix"]
|
||||
loaded_plugins_prefixes.append(pref)
|
||||
|
||||
|
||||
|
||||
# save the newly discovered plugins as options and default values
|
||||
conf.LOADED_PLUGINS = ccd('LOADED_PLUGINS', loaded_plugins_prefixes , c_d, 'Loaded plugins', '{"dataType":"array", "elements": [{"elementType" : "select", "elementOptions" : [{"multiple":"true"}] ,"transformers": []}]}', str(sorted(all_plugins_prefixes)), 'General')
|
||||
|
||||
@@ -296,12 +297,60 @@ def importConfigs (db, all_plugins):
|
||||
conf.plugins_once_run = False
|
||||
# -----------------
|
||||
# Plugins END
|
||||
|
||||
# HANDLE APP_CONF_OVERRIDE via app_conf_override.json
|
||||
# Assuming fullConfFolder is defined elsewhere
|
||||
app_conf_override_path = fullConfFolder + '/app_conf_override.json'
|
||||
|
||||
if os.path.exists(app_conf_override_path):
|
||||
with open(app_conf_override_path, 'r') as f:
|
||||
try:
|
||||
# Load settings_override from the JSON file
|
||||
settings_override = json.load(f)
|
||||
|
||||
# Loop through settings_override dictionary
|
||||
for setting_name, value in settings_override.items():
|
||||
# Ensure the value is treated as a string and passed directly
|
||||
if isinstance(value, str):
|
||||
# Log the value being passed
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
mylog('debug', [f"[Config] Setting override {setting_name} with value: {value}"])
|
||||
ccd(setting_name, value, c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True, 1)
|
||||
else:
|
||||
# Convert to string and log
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
mylog('debug', [f"[Config] Setting override {setting_name} with value: {str(value)}"])
|
||||
ccd(setting_name, str(value), c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True, 1)
|
||||
|
||||
except json.JSONDecodeError:
|
||||
mylog('none', [f"[Config] [ERROR] Setting override decoding JSON from {app_conf_override_path}"])
|
||||
else:
|
||||
mylog('debug', [f"[Config] File {app_conf_override_path} does not exist."])
|
||||
|
||||
# Check if app was upgraded
|
||||
with open(applicationPath + '/front/buildtimestamp.txt', 'r') as f:
|
||||
|
||||
buildTimestamp = int(f.read().strip())
|
||||
cur_version = conf.VERSION
|
||||
|
||||
mylog('debug', [f"[Config] buildTimestamp: '{buildTimestamp}'"])
|
||||
mylog('debug', [f"[Config] conf.VERSION : '{cur_version}'"])
|
||||
|
||||
if str(cur_version) != str(buildTimestamp):
|
||||
|
||||
mylog('none', ['[Config] App upgraded 🚀'])
|
||||
|
||||
# ccd(key, default, config_dir, name, inputtype, options, group, events=None, desc="", regex="", setJsonMetadata=None, overrideTemplate=None, forceDefault=False)
|
||||
ccd('VERSION', buildTimestamp , c_d, '_KEEP_', '_KEEP_', '_KEEP_', '_KEEP_', None, "_KEEP_", "", None, None, True)
|
||||
|
||||
write_notification(f'[Upgrade] : App upgraded 🚀 Please clear the cache: <ol> <li>Click OK below</li> <li>Clear the browser cache (shift + browser refresh button)</li> <li> Clear app cache with the 🔄 (reload) button in the header</li><li>Go to Settings and click Save</li> </ol> Check out new features and what has changed in the <a href="https://github.com/jokob-sk/NetAlertX/releases" target="_blank">📓 release notes</a>.', 'interrupt', timeNowTZ())
|
||||
|
||||
|
||||
# Insert settings into the DB
|
||||
sql.execute ("DELETE FROM Settings")
|
||||
# mylog('debug', [f"[Config] conf.mySettingsSQLsafe : '{conf.mySettingsSQLsafe}'"])
|
||||
sql.executemany ("""INSERT INTO Settings ("Code_Name", "Display_Name", "Description", "Type", "Options",
|
||||
"RegEx", "Value", "Group", "Events" ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", conf.mySettingsSQLsafe)
|
||||
"RegEx", "Value", "Group", "Events", "OverriddenByEnv" ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", conf.mySettingsSQLsafe)
|
||||
|
||||
db.commitDB()
|
||||
|
||||
|
||||
@@ -248,7 +248,11 @@ def execute_plugin(db, all_plugins, plugin, pluginsState = plugins_state() ):
|
||||
|
||||
for line in newLines:
|
||||
columns = line.split("|")
|
||||
# There have to be 9 or 13 columns
|
||||
# There have to be 9 or 13 columns
|
||||
if len(columns) not in [9, 13]:
|
||||
mylog('none', [f'[Plugins] Wrong number of input values, must be 9 or 13, got {len(columns)} from: {line}'])
|
||||
continue # Skip lines with incorrect number of columns
|
||||
|
||||
# Common part of the SQL parameters
|
||||
base_params = [
|
||||
0, # "Index" placeholder
|
||||
@@ -284,8 +288,6 @@ def execute_plugin(db, all_plugins, plugin, pluginsState = plugins_state() ):
|
||||
'null', # "HelpVal3"
|
||||
'null' # "HelpVal4"
|
||||
])
|
||||
else:
|
||||
mylog('none', [f'[Plugins] Wrong number of input values, must be 9 or 13, got {len(columns)} from: {line} '])
|
||||
|
||||
# Create a tuple containing values to be inserted into the database.
|
||||
# Each value corresponds to a column in the table in the order of the columns.
|
||||
|
||||
Reference in New Issue
Block a user