Skip to content

Commit a60ec9e

Browse files
committed
Merge branch 'main' of github.com:netalertx/NetAlertX
2 parents e1d206c + 2771a6e commit a60ec9e

12 files changed

Lines changed: 745 additions & 48 deletions

File tree

.github/skills/code-standards/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ description: NetAlertX coding standards and conventions. Use this when writing c
55

66
# Code Standards
77

8-
- ask me to review before going to each next step (mention n step out of x)
9-
- before starting, prepare implementation plan
8+
- ask me to review before going to each next step (mention n step out of x) (AI only)
9+
- before starting, prepare implementation plan (AI only)
1010
- ask me to review it and ask any clarifying questions first
1111
- add test creation as last step - follow repo architecture patterns - do not place in the root of /test
1212
- code has to be maintainable, no duplicate code
13-
- follow DRY principle
13+
- follow DRY principle - maintainability of code is more important than speed of implementation
1414
- code files should be less than 500 LOC for better maintainability
1515

1616
## File Length

.github/workflows/run-all-tests.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ name: 🧪 Manual Test Suite Selector
33
on:
44
workflow_dispatch:
55
inputs:
6+
run_all:
7+
description: '✅ Run ALL tests (overrides individual selectors)'
8+
type: boolean
9+
default: false
610
run_scan:
711
description: '📂 scan/ (Scan, Logic, Locks, IPs)'
812
type: boolean
@@ -23,6 +27,10 @@ on:
2327
description: '📂 ui/ (Selenium & Dashboard)'
2428
type: boolean
2529
default: false
30+
run_plugins:
31+
description: '📂 plugins/ (Sync insert schema-aware logic)'
32+
type: boolean
33+
default: false
2634
run_root_files:
2735
description: '📄 Root Test Files (WOL, Atomicity, etc.)'
2836
type: boolean
@@ -42,12 +50,20 @@ jobs:
4250
id: builder
4351
run: |
4452
PATHS=""
53+
54+
# run_all overrides everything
55+
if [ "${{ github.event.inputs.run_all }}" == "true" ]; then
56+
echo "final_paths=test/" >> $GITHUB_OUTPUT
57+
exit 0
58+
fi
59+
4560
# Folder Mapping with 'test/' prefix
4661
if [ "${{ github.event.inputs.run_scan }}" == "true" ]; then PATHS="$PATHS test/scan/"; fi
4762
if [ "${{ github.event.inputs.run_api }}" == "true" ]; then PATHS="$PATHS test/api_endpoints/ test/server/"; fi
4863
if [ "${{ github.event.inputs.run_backend }}" == "true" ]; then PATHS="$PATHS test/backend/ test/db/"; fi
4964
if [ "${{ github.event.inputs.run_docker_env }}" == "true" ]; then PATHS="$PATHS test/docker_tests/"; fi
5065
if [ "${{ github.event.inputs.run_ui }}" == "true" ]; then PATHS="$PATHS test/ui/"; fi
66+
if [ "${{ github.event.inputs.run_plugins }}" == "true" ]; then PATHS="$PATHS test/plugins/"; fi
5167
5268
# Root Files Mapping (files sitting directly in /test/)
5369
if [ "${{ github.event.inputs.run_root_files }}" == "true" ]; then

CONTRIBUTING.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
# 🤝 Contributing to NetAlertX
1+
# Contributing to NetAlertX
22

33
First off, **thank you** for taking the time to contribute! NetAlertX is built and improved with the help of passionate people like you.
44

55
---
66

7-
## 📂 Issues, Bugs, and Feature Requests
7+
## Issues, Bugs, and Feature Requests
88

99
Please use the [GitHub Issue Tracker](https://github.com/netalertx/NetAlertX/issues) for:
10-
- Bug reports 🐞
11-
- Feature requests 💡
12-
- Documentation feedback 📖
10+
- Bug reports
11+
- Feature requests
12+
- Documentation feedback
1313

1414
Before opening a new issue:
15-
- 🛑 [Check Common Issues & Debug Tips](https://docs.netalertx.com/DEBUG_TIPS#common-issues)
16-
- 🔍 [Search Closed Issues](https://github.com/netalertx/NetAlertX/issues?q=is%3Aissue+is%3Aclosed)
15+
- [Check Common Issues & Debug Tips](https://docs.netalertx.com/DEBUG_TIPS#common-issues)
16+
- [Search Closed Issues](https://github.com/netalertx/NetAlertX/issues?q=is%3Aissue+is%3Aclosed)
1717

1818
---
1919

20-
## 🚀 Submitting Pull Requests (PRs)
20+
## Submitting Pull Requests (PRs)
2121

2222
We welcome PRs to improve the code, docs, or UI!
2323

@@ -29,25 +29,30 @@ Please:
2929
- If relevant, add or update tests and documentation
3030
- For plugins, refer to the [Plugin Dev Guide](https://docs.netalertx.com/PLUGINS_DEV)
3131

32+
33+
## Code quality
34+
35+
- read and follow the [code-standards](/.github/skills/code-standards/SKILL.md)
36+
3237
---
3338

34-
## 🌟 First-Time Contributors
39+
## First-Time Contributors
3540

3641
New to open source? Check out these resources:
3742
- [How to Fork and Submit a PR](https://opensource.guide/how-to-contribute/)
3843
- Ask questions or get support in our [Discord](https://discord.gg/NczTUTWyRr)
3944

4045
---
4146

42-
## 🔐 Code of Conduct
47+
## Code of Conduct
4348

4449
By participating, you agree to follow our [Code of Conduct](./CODE_OF_CONDUCT.md), which ensures a respectful and welcoming community.
4550

4651
---
4752

48-
## 📬 Contact
53+
## Contact
4954

5055
If you have more in-depth questions or want to discuss contributing in other ways, feel free to reach out at:
51-
📧 [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX%20Contribution)
56+
[jokob.sk@gmail.com](mailto:jokob.sk@gmail.com?subject=NetAlertX%20Contribution)
5257

5358
We appreciate every contribution, big or small! 💙

front/devices.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,10 @@ function hasEnabledDeviceScanners() {
624624
// Update the title-bar ETA subtitle and the DataTables empty-state message.
625625
// Called on every nax:scanEtaUpdate; the inner ticker keeps the title bar live between events.
626626
function updateScanEtaDisplay(nextScanTime, currentState) {
627+
// Detect scan-finished transition BEFORE updating _currentStateAnchor.
628+
// justFinishedScanning is true only when the backend transitions scanning → idle.
629+
var justFinishedScanning = (currentState === 'Process: Idle') && isScanningState(_currentStateAnchor);
630+
627631
// Prefer the backend-computed values; keep previous anchors if not yet received.
628632
_nextScanTimeAnchor = nextScanTime || _nextScanTimeAnchor;
629633
_currentStateAnchor = currentState || _currentStateAnchor;
@@ -670,6 +674,13 @@ function tickTitleBar() {
670674
// Patch the visible cell text without triggering a server-side AJAX reload.
671675
$('#tableDevices tbody .dataTables_empty').html(newEmptyMsg);
672676
}
677+
678+
// When scanning just finished and the table is still empty, reload data so
679+
// newly discovered devices appear automatically. Skip reload if there are
680+
// already rows — no need to disturb the user's current view.
681+
if (justFinishedScanning && dt.page.info().recordsTotal === 0) {
682+
dt.ajax.reload(null, false); // false = keep current page position
683+
}
673684
}
674685

675686
tickTitleBar();

front/php/templates/language/fr_fr.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@
139139
"DevDetail_SessionTable_Duration": "Durée",
140140
"DevDetail_SessionTable_IP": "IP",
141141
"DevDetail_SessionTable_Order": "Ordre",
142-
"DevDetail_Shortcut_CurrentStatus": "État actuel",
142+
"DevDetail_Shortcut_CurrentStatus": "État",
143143
"DevDetail_Shortcut_DownAlerts": "Alertes de panne",
144144
"DevDetail_Shortcut_Presence": "Présence",
145145
"DevDetail_Shortcut_Sessions": "Sessions",
@@ -203,16 +203,16 @@
203203
"Device_MultiEdit_MassActions": "Actions en masse :",
204204
"Device_MultiEdit_No_Devices": "Aucun appareil sélectionné.",
205205
"Device_MultiEdit_Tooltip": "Attention. Ceci va appliquer la valeur de gauche à tous les appareils sélectionnés au-dessus.",
206-
"Device_NextScan_Imminent": "",
207-
"Device_NextScan_In": "",
208-
"Device_NoData_Help": "",
209-
"Device_NoData_Scanning": "",
210-
"Device_NoData_Title": "",
206+
"Device_NextScan_Imminent": "Imminent...",
207+
"Device_NextScan_In": "Prochain scan dans ",
208+
"Device_NoData_Help": "Si les appareils n'apparaissent pas après le scan, vérifiez vos paramètres SCAN_SUBNETS et la <a href=\"https://docs.netalertx.com/SUBNETS\" target=\"_blank\">documentation</a>.",
209+
"Device_NoData_Scanning": "En attente du premier scan - cela peut prendre quelques minutes après le premier paramétrage.",
210+
"Device_NoData_Title": "Aucun appareil trouvé pour le moment",
211211
"Device_Save_Failed": "Erreur à l'enregistrement de l'appareil",
212212
"Device_Save_Unauthorized": "Non autorisé - Jeton d'API invalide",
213213
"Device_Saved_Success": "Appareil enregistré avec succès",
214214
"Device_Saved_Unexpected": "La mise à jour de l'appareil a renvoyé une réponse inattendue",
215-
"Device_Scanning": "",
215+
"Device_Scanning": "Scan en cours...",
216216
"Device_Searchbox": "Rechercher",
217217
"Device_Shortcut_AllDevices": "Mes appareils",
218218
"Device_Shortcut_AllNodes": "Tous les nœuds",
@@ -322,7 +322,7 @@
322322
"Gen_AddDevice": "Ajouter un appareil",
323323
"Gen_Add_All": "Ajouter tous",
324324
"Gen_All_Devices": "Tous les appareils",
325-
"Gen_Archived": "",
325+
"Gen_Archived": "Archivés",
326326
"Gen_AreYouSure": "Êtes-vous sûr ?",
327327
"Gen_Backup": "Lancer la sauvegarde",
328328
"Gen_Cancel": "Annuler",
@@ -333,7 +333,7 @@
333333
"Gen_Delete": "Supprimer",
334334
"Gen_DeleteAll": "Supprimer tous",
335335
"Gen_Description": "Description",
336-
"Gen_Down": "",
336+
"Gen_Down": "Bas",
337337
"Gen_Error": "Erreur",
338338
"Gen_Filter": "Filtrer",
339339
"Gen_Flapping": "",
@@ -342,7 +342,7 @@
342342
"Gen_Invalid_Value": "Une valeur invalide a été renseignée",
343343
"Gen_LockedDB": "Erreur - La base de données est peut-être verrouillée - Vérifier avec les outils de dév via F12 -> Console ou essayer plus tard.",
344344
"Gen_NetworkMask": "Masque réseau",
345-
"Gen_New": "",
345+
"Gen_New": "Nouveau",
346346
"Gen_Offline": "Hors ligne",
347347
"Gen_Okay": "OK",
348348
"Gen_Online": "En ligne",
@@ -360,7 +360,7 @@
360360
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
361361
"Gen_SelectToPreview": "Sélectionnez pour prévisualiser",
362362
"Gen_Selected_Devices": "Appareils sélectionnés :",
363-
"Gen_Sleeping": "",
363+
"Gen_Sleeping": "Inactif",
364364
"Gen_Subnet": "Sous-réseau",
365365
"Gen_Switch": "Basculer",
366366
"Gen_Upd": "Mise à jour réussie",
@@ -804,4 +804,4 @@
804804
"settings_system_label": "Système",
805805
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
806806
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage."
807-
}
807+
}

front/php/templates/language/ru_ru.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@
203203
"Device_MultiEdit_MassActions": "Массовые действия:",
204204
"Device_MultiEdit_No_Devices": "Устройства не выбраны.",
205205
"Device_MultiEdit_Tooltip": "Осторожно. При нажатии на эту кнопку значение слева будет применено ко всем устройствам, выбранным выше.",
206-
"Device_NextScan_Imminent": "Предстоящий...",
206+
"Device_NextScan_Imminent": "Скоро...",
207207
"Device_NextScan_In": "Следующее сканирование примерно через· ",
208208
"Device_NoData_Help": "Если устройства не отображаются после сканирования, проверьте настройку SCAN_SUBNETS и <a href=\"https://docs.netalertx.com/SUBNETS\" target=\"_blank\">документацию</a>.",
209209
"Device_NoData_Scanning": "Ожидание первого сканирования — это может занять несколько минут после первоначальной настройки.",
@@ -231,7 +231,7 @@
231231
"Device_TableHead_FQDN": "FQDN",
232232
"Device_TableHead_Favorite": "Избранное",
233233
"Device_TableHead_FirstSession": "Первый сеанс",
234-
"Device_TableHead_Flapping": "",
234+
"Device_TableHead_Flapping": "Нестабильный",
235235
"Device_TableHead_GUID": "GUID",
236236
"Device_TableHead_Group": "Группа",
237237
"Device_TableHead_IPv4": "IPv4",
@@ -322,7 +322,7 @@
322322
"Gen_AddDevice": "Добавить устройство",
323323
"Gen_Add_All": "Добавить все",
324324
"Gen_All_Devices": "Все устройства",
325-
"Gen_Archived": "",
325+
"Gen_Archived": "Архивировано",
326326
"Gen_AreYouSure": "Вы уверены?",
327327
"Gen_Backup": "Запустить резервное копирование",
328328
"Gen_Cancel": "Отмена",
@@ -333,16 +333,16 @@
333333
"Gen_Delete": "Удалить",
334334
"Gen_DeleteAll": "Удалить все",
335335
"Gen_Description": "Описание",
336-
"Gen_Down": "",
336+
"Gen_Down": "Лежит",
337337
"Gen_Error": "Ошибка",
338338
"Gen_Filter": "Фильтр",
339-
"Gen_Flapping": "",
339+
"Gen_Flapping": "Нестабильный",
340340
"Gen_Generate": "Генерировать",
341341
"Gen_InvalidMac": "Неверный Mac-адрес.",
342342
"Gen_Invalid_Value": "Введено некорректное значение",
343343
"Gen_LockedDB": "ОШИБКА - Возможно, база данных заблокирована. Проверьте инструменты разработчика F12 -> Консоль или повторите попытку позже.",
344344
"Gen_NetworkMask": "Маска сети",
345-
"Gen_New": "",
345+
"Gen_New": "Новый",
346346
"Gen_Offline": "Оффлайн",
347347
"Gen_Okay": "OK",
348348
"Gen_Online": "Онлайн",
@@ -360,7 +360,7 @@
360360
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
361361
"Gen_SelectToPreview": "Выберите для предварительного просмотра",
362362
"Gen_Selected_Devices": "Выбранные устройства:",
363-
"Gen_Sleeping": "",
363+
"Gen_Sleeping": "Спящий",
364364
"Gen_Subnet": "Подсеть",
365365
"Gen_Switch": "Переключить",
366366
"Gen_Upd": "Успешное обновление",
@@ -590,8 +590,8 @@
590590
"PIALERT_WEB_PROTECTION_name": "Включить вход",
591591
"PLUGINS_KEEP_HIST_description": "Сколько записей результатов сканирования истории плагинов следует хранить (для каждого плагина, а не для конкретного устройства).",
592592
"PLUGINS_KEEP_HIST_name": "История плагинов",
593-
"PRAGMA_JOURNAL_SIZE_LIMIT_description": "",
594-
"PRAGMA_JOURNAL_SIZE_LIMIT_name": "",
593+
"PRAGMA_JOURNAL_SIZE_LIMIT_description": "Максимальный размер SQLite WAL (журнал упреждающей записи) в МБ перед запуском автоматических контрольных точек. Более низкие значения (10–20 МБ) уменьшают использование диска/хранилища, но увеличивают загрузку ЦП во время сканирования. Более высокие значения (50–100 МБ) уменьшают нагрузку на процессор во время операций, но могут использовать больше оперативной памяти и дискового пространства. Значение по умолчанию <code>50 МБ</code> компенсирует и то, и другое. Полезно для систем с ограниченными ресурсами, таких как устройства NAS с SD-картами. Перезапустите сервер, чтобы изменения вступили в силу после сохранения настроек.",
594+
"PRAGMA_JOURNAL_SIZE_LIMIT_name": "Ограничение размера WAL (МБ)",
595595
"Plugins_DeleteAll": "Удалить все (фильтры игнорируются)",
596596
"Plugins_Filters_Mac": "Фильтр MAC-адреса",
597597
"Plugins_History": "История событий",

front/plugins/sync/sync.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,27 +222,30 @@ def main():
222222
extra = '',
223223
foreignKey = device['devGUID'])
224224

225+
# Resolve the actual columns that exist in the Devices table once.
226+
# This automatically excludes computed/virtual fields (e.g. devStatus,
227+
# devIsSleeping) and 'rowid' without needing a maintained exclusion list.
228+
cursor.execute("PRAGMA table_info(Devices)")
229+
db_columns = {row[1] for row in cursor.fetchall()}
230+
225231
# Filter out existing devices
226232
new_devices = [device for device in device_data if device['devMac'] not in existing_mac_addresses]
227233

228-
# Remove 'rowid' key if it exists
229-
for device in new_devices:
230-
device.pop('rowid', None)
231-
device.pop('devStatus', None)
232-
233234
mylog('verbose', [f'[{pluginName}] All devices: "{len(device_data)}"'])
234235
mylog('verbose', [f'[{pluginName}] New devices: "{len(new_devices)}"'])
235236

236237
# Prepare the insert statement
237238
if new_devices:
238239

239-
# creating insert statement, removing 'rowid', 'devStatus' as handled on the target and devStatus is resolved on the fly
240-
columns = ', '.join(k for k in new_devices[0].keys() if k not in ['rowid', 'devStatus'])
241-
placeholders = ', '.join('?' for k in new_devices[0] if k not in ['rowid', 'devStatus'])
240+
# Only keep keys that are real columns in the target DB; computed
241+
# or unknown fields are silently dropped regardless of source schema.
242+
insert_cols = [k for k in new_devices[0].keys() if k in db_columns]
243+
columns = ', '.join(insert_cols)
244+
placeholders = ', '.join('?' for _ in insert_cols)
242245
sql = f'INSERT INTO Devices ({columns}) VALUES ({placeholders})'
243246

244-
# Extract values for the new devices
245-
values = [tuple(device.values()) for device in new_devices]
247+
# Extract only the whitelisted column values for each device
248+
values = [tuple(device.get(col) for col in insert_cols) for device in new_devices]
246249

247250
mylog('verbose', [f'[{pluginName}] Inserting Devices SQL : "{sql}"'])
248251
mylog('verbose', [f'[{pluginName}] Inserting Devices VALUES: "{values}"'])

server/api_server/graphql_endpoint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ def resolve_langStrings(self, info, langCode=None, langStringKey=None, fallback_
563563
langStrings = []
564564

565565
# --- CORE JSON FILES ---
566-
language_folder = '/app/front/php/templates/language/language_definitions/'
566+
language_folder = '/app/front/php/templates/language/'
567567
if os.path.exists(language_folder):
568568
for filename in os.listdir(language_folder):
569569
if filename.endswith('.json') and filename != 'languages.json':

0 commit comments

Comments
 (0)