Skip to content

Conversation

@jokob-sk
Copy link
Collaborator

@jokob-sk jokob-sk commented Nov 2, 2025

Summary by CodeRabbit

  • New Features

    • GraphQL now returns language strings with filtering and fallback
    • New Logs API to purge allowed logs and queue user actions
    • App state exposes application version
  • Bug Fixes

    • Standardized timestamp source across notifications, plugins and scans
    • Improved timezone handling and timestamp normalization
  • Documentation

    • Added Logs API docs; expanded GraphQL (LangStrings) and plugin developer guides
  • Tests

    • End-to-end tests added for GraphQL and Logs endpoints

jokob-sk and others added 3 commits November 2, 2025 22:21
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

Important

Review skipped

More than 25% of the files skipped due to max files limit. The review is being skipped to prevent a low-quality review.

69 files out of 239 files are above the max files limit of 100. Please upgrade to Pro plan to get higher limits.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR centralizes datetime utilities into server/utils/datetime_utils.py, updates callers to use the new APIs (notably timeNowDB()), adds Logs API endpoints and a user-events execution queue, extends app state with appVersion, renames plugin state fields (lastChangedlastDataChange), adds GraphQL LangStrings support, adjusts numerous import paths to utils.*, and updates docs and CI workflows.

Changes

Cohort / File(s) Summary
Datetime core
server/utils/datetime_utils.py, server/helper.py
New comprehensive datetime utilities module added; legacy time helpers removed from helper.py; getBuildTimeStamp() replaced by getBuildTimeStampAndVersion() (returns tuple) and internal references updated.
App state & init
server/app_state.py, server/initialise.py
appVersion added to state and constructors; state timestamps use timeNowDB(); initialization/upgrade flow updated to use new build/version API and pass appVersion through updateState.
Server core & logger
server/logger.py, server/plugin_helper.py, server/__main__.py, server/api.py
Time helper imports moved to utils.datetime_utils; removed inline timeNowTZ() definitions; plugin object created timestamp now uses timeNowDB().
Server API — new endpoints & models
server/api_server/api_server_start.py, server/api_server/logs_endpoint.py, server/models/user_events_queue_instance.py, test/api_endpoints/test_logs_endpoints.py
Added 404 handler; /logs and /logs/add-to-execution-queue endpoints; clean_log() and UserEventsQueueInstance.add_event() to enqueue actions (timestamp+GUID); tests for logs endpoints added; responses standardized.
Server API — GraphQL
server/api_server/graphql_endpoint.py, test/api_endpoints/test_graphq_endpoints.py
Added LangString and LangStringResult types and langStrings query with caching, fallback-to-en_us, filtering, and tests.
Server API — endpoint time/format updates
multiple server/api_server/* (devices, device, history, events, sessions, sync, api_server_start)
Replaced date/time helpers with utils.datetime_utils equivalents; swapped timeNowTZ()timeNowDB() where applicable; added timezone-aware formatting in some endpoints and standardized error payload shapes.
Server scan & name resolution
server/scan/device_handling.py, server/scan/name_resolution.py, server/scan/session_events.py, server/scan/device_heuristics.py
Timestamps migrated to timeNowDB(); added check_plugin_data_changed() and normalization/logging for plugin last-checked/lastDataChange; added trace log in name cleaning.
Server messaging & models
server/messaging/in_app.py, server/messaging/reporting.py, server/models/notification_instance.py
Notification timestamps and model timestamps switched to timeNowDB(); minor logging/query adjustments.
Plugin manager & plugin state
server/plugin.py
Renamed per-plugin state field lastChangedlastDataChange, name_plugins_checkedplugin_checks; added internal _build_cache; timestamp sources switched to timeNowDB().
Front plugins — time/import migrations
many front/plugins/* (publishers, sync, speedtest, internet_ip, etc.)
Replaced timeNowTZ() usages with timeNowDB() and adjusted imports to utils.datetime_utils; removed many unused timeNowTZ imports.
Front plugins — import path updates
multiple front/plugins/* (plugin_utils/crypto_utils → utils.plugin_utils/utils.crypto_utils)
Updated plugin/crypto import paths to utils.* where applicable; removed unused imports and some DB init removal.
Front PHP UI changes
front/php/components/logs.php, front/php/server/util.php
Improved log file reading with size checks and allowlist-related comments; added API-superceded annotations.
Tests
test/api_endpoints/*
Added GraphQL and logs endpoint tests; updated many tests to use timeNowDB() or remove timeNowTZ imports.
Docs — APIs & plugins
docs/API.md, docs/API_GRAPHQL.md, docs/API_LOGS.md, docs/PLUGINS_DEV_CONFIG.md, docs/NOTIFICATIONS.md
Documented new Logs API and GraphQL LangStrings; reworked plugins developer doc and notification filters; updated links and wording.
Docs — installation & links
README.md, docs/*
Replaced Docker installation links to local DOCKER_INSTALLATION.md.
CI / Docker
.github/workflows/*, Dockerfile
Dev workflow: timestamped dev version output; prod workflow: release-tag-driven versioning and QEMU step; Dockerfile copies .VERSION into image.
Minor/other
many files across front/plugins/*, server/workflows/*, server/api_server/*, tests
Numerous import cleanups removing unused time helpers and switching import paths to utils.*; small logging and comment updates.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Utils as utils.datetime_utils
    participant Plugin as Plugin
    participant DB as Database

    App->>Utils: timeNowDB()
    Utils-->>App: DB-safe timestamp (string)
    Plugin->>Utils: timeNowDB() for secondaryId/state
    Utils-->>Plugin: timestamp
    Plugin->>DB: persist entries with timestamp
    DB-->>Plugin: ack
Loading
sequenceDiagram
    participant Client as API Client
    participant Server as API Server
    participant Endpoint as logs_endpoint.py
    participant Queue as UserEventsQueue
    participant File as execution_queue.log
    participant Utils as utils.datetime_utils

    Client->>Server: POST /logs/add-to-execution-queue {action}
    Server->>Endpoint: api_add_to_execution_queue()
    Endpoint->>Queue: add_event(action)
    Queue->>Utils: timeNowDB()
    Utils-->>Queue: timestamp
    Queue->>Queue: generate uuid
    Queue->>File: write "[timestamp]|[uuid]|[action]\n"
    File-->>Queue: success
    Queue-->>Endpoint: (True, msg)
    Endpoint-->>Client: 200 {success: true, message: msg}
Loading
sequenceDiagram
    participant Client as GraphQL Client
    participant Server as GraphQL Server
    participant Res as graphql_endpoint.py
    participant Cache as In-Memory Cache
    participant FS as File System

    Client->>Server: Query langStrings(langCode?, langStringKey?)
    Server->>Res: resolve_langStrings(...)
    Res->>Cache: check core/plugin cache
    alt cache hit
        Cache-->>Res: return cached
    else
        Res->>FS: read core lang JSONs
        FS-->>Res: core data
        Res->>FS: read plugin lang JSON
        FS-->>Res: plugin data
        Res->>Cache: store merged results
    end
    Res->>Res: apply filters + fallback
    Res-->>Server: LangStringResult {langStrings, count}
    Server-->>Client: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Areas requiring extra attention:

  • Time semantics: ensure timezone-aware vs DB/UTC string behavior of timeNowDB() matches all call sites and persisted formats.
  • Import path changes: verify no circular imports introduced by moving utilities to utils.*.
  • Plugin state rename: confirm backward compatibility when reading persisted plugin states (lastChangedlastDataChange).
  • GraphQL resolver: review cache behavior, file-reading error handling, and plugin/core merging logic.
  • Logs queue: confirm file write concurrency/safety and allowlist enforcement in clean_log().

Possibly related PRs

  • Next release #1245 — touches build/version utilities and related initialization logic similarly to the introduction of getBuildTimeStampAndVersion() and version propagation in this PR.

Poem

🐰 I hopped through files and changed the time,
Moved clocks to utils in tidy rhyme.
Logs now queue with GUID and cheer,
LangStrings sing so clients hear,
App version tucked in state — refactor sublime.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.05% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Next release' is vague and does not clearly communicate the main changes in this extensive pull request that refactors datetime utilities, adds logging APIs, improves documentation, and updates multiple plugin integrations. Use a more specific title that highlights the primary objective, such as 'Refactor datetime utilities and consolidate time handling across codebase' or 'Reorganize datetime helpers and add logging API endpoints'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90a07c6 and db18ca7.

📒 Files selected for processing (9)
  • front/plugins/arp_scan/script.py (0 hunks)
  • front/plugins/dhcp_servers/script.py (1 hunks)
  • front/plugins/nmap_scan/script.py (0 hunks)
  • front/plugins/plugin_helper.py (1 hunks)
  • server/api_server/device_endpoint.py (4 hunks)
  • server/app_state.py (2 hunks)
  • server/helper.py (0 hunks)
  • server/plugin.py (5 hunks)
  • server/scan/device_handling.py (4 hunks)
💤 Files with no reviewable changes (3)
  • front/plugins/arp_scan/script.py
  • server/helper.py
  • front/plugins/nmap_scan/script.py
🧰 Additional context used
📓 Path-based instructions (4)
front/plugins/plugin_helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Files:

  • front/plugins/plugin_helper.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • front/plugins/plugin_helper.py
  • server/scan/device_handling.py
  • server/api_server/device_endpoint.py
  • server/app_state.py
  • front/plugins/dhcp_servers/script.py
  • server/plugin.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/device_endpoint.py
front/plugins/*/script.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

front/plugins/*/script.py: Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.
During plugin processing, collect results with 'Plugin_Objects.add_object(...)' and call 'plugin_objects.write_result_file()' exactly once at the end of the script.
Do not write ad-hoc files for plugin results; only generate 'last_result..log' using 'Plugin_Objects'.
Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Files:

  • front/plugins/dhcp_servers/script.py
🧠 Learnings (5)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/plugin_helper.py : Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Applied to files:

  • front/plugins/plugin_helper.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/api_server/device_endpoint.py
📚 Learning: 2025-11-02T02:22:10.949Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1261
File: server/app_state.py:106-115
Timestamp: 2025-11-02T02:22:10.949Z
Learning: In server/app_state.py, the pluginsStates parameter always contains complete plugin state objects with the structure: {"PLUGIN_NAME": {"lastChanged": "...", "totalObjects": N, "newObjects": N, "changedObjects": N}}. Type validation before calling .update() is not needed as the maintainer guarantees well-formed objects are always supplied.

Applied to files:

  • server/app_state.py
  • server/plugin.py
📚 Learning: 2025-10-19T15:29:46.423Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1230
File: front/plugins/dhcp_servers/script.py:44-44
Timestamp: 2025-10-19T15:29:46.423Z
Learning: In the NetAlertX dhcp_servers plugin (front/plugins/dhcp_servers/script.py), the nmap command uses both 'sudo' and '--privileged' flag to maintain cross-platform compatibility. While the hardened Docker image stubs sudo and uses capabilities, hardware installations (Debian 12, Ubuntu 24) and the Debian Dockerfile require sudo for raw socket access. This approach ensures the plugin works across all deployment targets.

Applied to files:

  • front/plugins/dhcp_servers/script.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Applied to files:

  • server/plugin.py
🧬 Code graph analysis (4)
server/scan/device_handling.py (1)
server/helper.py (1)
  • timeNowTZ (35-45)
server/api_server/device_endpoint.py (1)
server/helper.py (5)
  • is_random_mac (632-647)
  • is_random_mac (675-686)
  • format_date (101-103)
  • get_setting_value (326-379)
  • timeNowTZ (35-45)
server/app_state.py (1)
server/helper.py (1)
  • timeNowTZ (35-45)
server/plugin.py (1)
server/helper.py (1)
  • timeNowTZ (35-45)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (2)
server/scan/device_handling.py (2)

6-6: LGTM!

The datetime import is needed for the type checking on line 544.


59-59: LGTM!

The ISO 8601 timestamp format is appropriate for database storage and aligns with the PR's standardization goal.

sql.execute("SELECT CURRENT_TIMESTAMP")
row = sql.fetchone()
pm.name_plugins_checked = row[0] if row else None
pm.name_plugins_checked = timeNowTZ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Ensure timezone consistency for datetime comparisons.

Line 653 uses timeNowTZ() which returns a naive datetime when conf.tz is not set, but line 59 uses timeNowTZ().astimezone().isoformat() for database storage. For the comparison on line 552 to work correctly without TypeError, both last_checked and latest_state must be consistently either timezone-aware or naive.

Apply this diff to ensure timezone-aware datetime:

-    pm.name_plugins_checked = timeNowTZ()
+    pm.name_plugins_checked = timeNowTZ().astimezone()

This ensures last_checked is always timezone-aware, matching the behavior of parsed ISO timestamps from plugin states.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pm.name_plugins_checked = timeNowTZ()
pm.name_plugins_checked = timeNowTZ().astimezone()
🤖 Prompt for AI Agents
In server/scan/device_handling.py around line 653, pm.name_plugins_checked is
being set with timeNowTZ() which can return a naive datetime; update this
assignment to ensure the value is timezone-aware (e.g., call
timeNowTZ().astimezone()) so it matches the ISO-parsed plugin state timestamps
and avoids TypeError during comparisons.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
server/api_server/device_endpoint.py (1)

190-191: Consider consolidating the timestamp computation.

Both lines call timeNowTZ().astimezone().isoformat() separately, which could result in slightly different timestamps. Consider computing once at the function start and reusing it.

Apply this diff:

 def set_device_data(mac, data):
     """Update or create a device."""
+    now = timeNowTZ().astimezone().isoformat()
     if data.get("createNew", False):
         sql = """
         INSERT INTO Devices (
@@ -187,8 +188,8 @@
             data.get("devSkipRepeated", 0),
             data.get("devIsNew", 0),
             data.get("devIsArchived", 0),
-            data.get("devLastConnection", timeNowTZ().astimezone().isoformat()),
-            data.get("devFirstConnection", timeNowTZ().astimezone().isoformat()),
+            data.get("devLastConnection", now),
+            data.get("devFirstConnection", now),
             data.get("devLastIP", ""),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db18ca7 and c52e44f.

📒 Files selected for processing (4)
  • server/api_server/device_endpoint.py (4 hunks)
  • server/helper.py (1 hunks)
  • server/scan/device_handling.py (4 hunks)
  • test/test_dbquery_endpoints.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • test/test_dbquery_endpoints.py
  • server/api_server/device_endpoint.py
  • server/helper.py
  • server/scan/device_handling.py
test/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Tests must reside under 'test/' and use pytest.

Files:

  • test/test_dbquery_endpoints.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/device_endpoint.py
server/helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Files:

  • server/helper.py
🧠 Learnings (1)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/api_server/device_endpoint.py
  • server/helper.py
🧬 Code graph analysis (4)
test/test_dbquery_endpoints.py (1)
server/helper.py (1)
  • timeNowTZ (35-45)
server/api_server/device_endpoint.py (1)
server/helper.py (1)
  • timeNowTZ (35-45)
server/helper.py (1)
front/js/common.js (1)
  • tz (375-375)
server/scan/device_handling.py (2)
server/helper.py (1)
  • timeNowTZ (35-45)
server/logger.py (2)
  • timeNowTZ (16-20)
  • mylog (86-92)
🪛 Ruff (0.14.3)
server/helper.py

109-109: Do not catch blind exception: Exception

(BLE001)

server/scan/device_handling.py

550-550: Do not catch blind exception: Exception

(BLE001)


558-558: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (7)
server/api_server/device_endpoint.py (1)

31-31: LGTM! Past issue resolved.

Hoisting now before the conditional ensures it's defined for all code paths, addressing the UnboundLocalError flagged in previous reviews.

test/test_dbquery_endpoints.py (1)

43-48: LGTM! Consistent timestamp usage.

Good practice to compute the timestamp once and reuse it for both devFirstConnection and devLastConnection fields, ensuring consistency.

server/scan/device_handling.py (2)

545-561: Timestamp normalization logic is sound.

The code properly normalizes plugin state timestamps to datetime objects before comparison, addressing the type-mixing concerns from previous reviews. The broad Exception catches (flagged by static analysis) are acceptable here since they handle unpredictable external data formats and include proper logging for debugging.


59-59: LGTM! ISO 8601 standardization.

The change to timeNowTZ().astimezone().isoformat() aligns with the PR's goal of standardizing timestamps across the codebase.

server/helper.py (3)

88-99: LGTM! Robust datetime parsing.

The two-stage parsing (ISO8601 first, then RFC1123/HTTP) handles the most common timestamp formats gracefully, with appropriate fallback to None on failure.


101-110: Function logic is correct.

The timezone assignment for naive datetimes (lines 104-107) properly uses the application timezone from conf.tz. The broad Exception catch (line 109, flagged by static analysis) is acceptable for a user-facing formatting function that needs to handle malformed input gracefully by returning "invalid".


112-153: All callers properly handle the dict return type — no breaking change issues found.

The verification confirms all four usages of format_date_diff in server/api_server/sessions_endpoint.py are already accessing the dict keys (["text"], ["total_minutes"]) correctly. The breaking change has been fully accommodated across the codebase.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
server/scan/device_handling.py (1)

536-543: Prefer specific exception types over bare Exception.

The logic correctly normalizes last_checked to a datetime object. However, catching bare Exception is overly broad. The parser.parse() method primarily raises ValueError and TypeError on failure.

Apply this diff to catch specific exceptions:

     # Normalize last_checked to datetime if it's a string  
     if isinstance(last_checked, str):  
         try:  
             last_checked = parser.parse(last_checked)  
-        except Exception as e:  
+        except (ValueError, TypeError) as e:  
             mylog('none', f'[Update Device Name] Could not parse last_checked timestamp: {last_checked!r} ({e})')  
             last_checked = None  
     elif not isinstance(last_checked, datetime.datetime):  
         last_checked = None
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c52e44f and 6dd7251.

📒 Files selected for processing (1)
  • server/scan/device_handling.py (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/scan/device_handling.py
🧬 Code graph analysis (1)
server/scan/device_handling.py (2)
server/helper.py (1)
  • timeNowTZ (35-45)
server/logger.py (2)
  • timeNowTZ (16-20)
  • mylog (86-92)
🪛 Ruff (0.14.3)
server/scan/device_handling.py

539-539: Do not catch blind exception: Exception

(BLE001)


560-560: Do not catch blind exception: Exception

(BLE001)


568-568: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (4)
server/scan/device_handling.py (4)

6-6: LGTM!

The datetime import is correctly added to support the type checking operations introduced in the update_devices_names function.


59-59: LGTM!

The change to ISO 8601 format with .astimezone().isoformat() correctly standardizes timestamp representation and ensures timezone awareness.


574-574: LGTM!

The comparison logic is correct, assuming both last_checked and latest_state are properly normalized datetime objects (which they will be once the indentation issue in lines 565-570 is resolved).


675-675: LGTM!

The timestamp update correctly uses ISO 8601 format with timezone awareness, consistent with the standardization objectives and the change on line 59.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
front/plugins/nmap_dev_scan/nmap_dev.py (3)

50-51: Remove unused database connection.

The database connection is opened but never used or closed, resulting in a resource leak.

Apply this diff:

-    # Create a database connection
-    db = DB()  # instance of class DB
-    db.open()
-

68-80: Inconsistent and non-standard MAC address handling.

The primaryId uses lowercased MAC (line 72) while foreignKey uses the original case (line 79). More importantly, nmap_dev.py should follow the established pattern in the codebase: import and use normalize_mac() from plugin_helper.py, as done in snmp_discovery/script.py. The current .lower() approach is inconsistent with the codebase standard.

Apply this fix:

  1. Import normalize_mac at the top of nmap_dev.py:
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64, normalize_mac
  1. Update lines 72 and 79 to use normalize_mac():
     for device in unique_devices:

         plugin_objects.add_object(
         # "MAC", "IP", "Name", "Vendor", "Interface"
-        primaryId   = device['mac'].lower(),
+        primaryId   = normalize_mac(device['mac']),
         secondaryId = device['ip'],
         watched1    = device['name'],
         watched2    = device['vendor'],
         watched3    = device['interface'],
         watched4    = '',
         extra       = '',
-        foreignKey  = device['mac'])
+        foreignKey  = normalize_mac(device['mac']))

193-200: Use normalize_mac from plugin_helper.py to normalize generated MAC addresses before writing to Plugin_Objects.

The generated MAC at line 173 is written directly to Plugin_Objects without normalization. According to project guidelines, all MAC addresses should be normalized before writing results. Apply normalization to the generated MAC:

if mac == '' and fakeMac:
    mac = normalize_mac(string_to_mac_hash(ip))

Add the import if not present:

from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64, normalize_mac
front/plugins/_publisher_mqtt/mqtt.py (1)

558-573: Fix type mismatch: timeNowDB() returns string, not datetime.

The fallback path assigns timeNowDB() to parsed_datetime, but timeNowDB() returns a string (e.g., '2025-11-04 18:09:11'), while line 573 expects a datetime object to call .isoformat(). This will cause an AttributeError.

Apply this diff to fix the type mismatch:

     except ValueError:
         mylog('verbose', [f"[{pluginName}]  Timestamp conversion failed of string '{datetime_str}'"])
         # Use the current time if the input format is invalid
-        parsed_datetime = timeNowDB()  
+        parsed_datetime = datetime.now(conf.tz)
🧹 Nitpick comments (5)
front/plugins/ddns_update/script.py (1)

14-14: Remove unused import for consistency.

The datetime import is not used anywhere in this file and should be removed, similar to the timeNowTZ cleanup.

Apply this diff:

-from datetime import datetime
front/plugins/__test/test.py (1)

9-10: Consider removing unused standard library imports.

The datetime and time imports don't appear to be used in the current code. While this is a development/test plugin where such imports might be kept available for ad-hoc testing, removing them would improve code clarity.

Apply this diff if you'd like to clean up:

-from datetime import datetime
-import time
front/plugins/nmap_dev_scan/nmap_dev.py (1)

16-16: Remove unused import.

The datetime import is not used anywhere in this file.

Apply this diff:

-from datetime import datetime
server/messaging/reporting.py (1)

126-128: Use "debug" log level for SQL query logging.

The SQL query is logged at "none" level, meaning it will always appear in logs. This should use "debug" level instead.

Apply this diff:

-        mylog("none", sqlQuery)            
+        mylog("debug", sqlQuery)            
server/scan/device_handling.py (1)

553-560: Narrow the exception handler for better error diagnostics.

Line 559 catches bare Exception, which can mask unexpected errors. Since timestamp parsing typically raises ValueError or TypeError, narrow the handler to those specific exceptions.

Apply this diff:

         elif isinstance(state_updated, str):
             try:
                 state_times.append(parser.parse(state_updated))
-            except Exception as e:
+            except (ValueError, TypeError) as e:
                 mylog('none', f'[Update Device Name] Failed to parse timestamp for {p}: {state_updated!r} ({e})')
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6dd7251 and 59477e7.

📒 Files selected for processing (67)
  • front/plugins/__template/rename_me.py (1 hunks)
  • front/plugins/__test/test.py (1 hunks)
  • front/plugins/_publisher_apprise/apprise.py (2 hunks)
  • front/plugins/_publisher_email/email_smtp.py (2 hunks)
  • front/plugins/_publisher_mqtt/mqtt.py (2 hunks)
  • front/plugins/_publisher_ntfy/ntfy.py (2 hunks)
  • front/plugins/_publisher_pushover/pushover.py (2 hunks)
  • front/plugins/_publisher_pushsafer/pushsafer.py (2 hunks)
  • front/plugins/_publisher_telegram/tg.py (2 hunks)
  • front/plugins/_publisher_webhook/webhook.py (2 hunks)
  • front/plugins/arp_scan/script.py (1 hunks)
  • front/plugins/csv_backup/script.py (1 hunks)
  • front/plugins/db_cleanup/script.py (1 hunks)
  • front/plugins/ddns_update/script.py (1 hunks)
  • front/plugins/dhcp_leases/script.py (1 hunks)
  • front/plugins/dhcp_servers/script.py (2 hunks)
  • front/plugins/dig_scan/digscan.py (1 hunks)
  • front/plugins/freebox/freebox.py (1 hunks)
  • front/plugins/icmp_scan/icmp.py (1 hunks)
  • front/plugins/internet_ip/script.py (2 hunks)
  • front/plugins/internet_speedtest/script.py (2 hunks)
  • front/plugins/ipneigh/ipneigh.py (1 hunks)
  • front/plugins/luci_import/script.py (1 hunks)
  • front/plugins/maintenance/maintenance.py (1 hunks)
  • front/plugins/nbtscan_scan/nbtscan.py (1 hunks)
  • front/plugins/nmap_dev_scan/nmap_dev.py (1 hunks)
  • front/plugins/nmap_scan/script.py (2 hunks)
  • front/plugins/nslookup_scan/nslookup.py (1 hunks)
  • front/plugins/omada_sdn_imp/omada_sdn.py (1 hunks)
  • front/plugins/plugin_helper.py (2 hunks)
  • front/plugins/snmp_discovery/script.py (1 hunks)
  • front/plugins/sync/sync.py (6 hunks)
  • front/plugins/unifi_api_import/unifi_api_import.py (1 hunks)
  • front/plugins/unifi_import/script.py (1 hunks)
  • front/plugins/vendor_update/script.py (1 hunks)
  • front/plugins/wake_on_lan/wake_on_lan.py (1 hunks)
  • front/plugins/website_monitor/script.py (1 hunks)
  • server/api_server/api_server_start.py (1 hunks)
  • server/api_server/device_endpoint.py (4 hunks)
  • server/api_server/events_endpoint.py (1 hunks)
  • server/api_server/sessions_endpoint.py (1 hunks)
  • server/api_server/sync_endpoint.py (3 hunks)
  • server/app_state.py (3 hunks)
  • server/helper.py (3 hunks)
  • server/initialise.py (3 hunks)
  • server/logger.py (1 hunks)
  • server/messaging/in_app.py (2 hunks)
  • server/messaging/reporting.py (2 hunks)
  • server/models/notification_instance.py (5 hunks)
  • server/plugin.py (10 hunks)
  • server/plugin_utils.py (1 hunks)
  • server/scan/device_handling.py (5 hunks)
  • server/scan/device_heuristics.py (1 hunks)
  • server/scan/session_events.py (3 hunks)
  • server/workflows/actions.py (1 hunks)
  • server/workflows/app_events.py (1 hunks)
  • server/workflows/conditions.py (1 hunks)
  • server/workflows/manager.py (1 hunks)
  • server/workflows/triggers.py (1 hunks)
  • test/test_dbquery_endpoints.py (2 hunks)
  • test/test_device_endpoints.py (1 hunks)
  • test/test_devices_endpoints.py (1 hunks)
  • test/test_graphq_endpoints.py (1 hunks)
  • test/test_history_endpoints.py (1 hunks)
  • test/test_nettools_endpoints.py (1 hunks)
  • test/test_sessions_endpoints.py (6 hunks)
  • test/test_settings_endpoints.py (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • front/plugins/ipneigh/ipneigh.py
  • front/plugins/snmp_discovery/script.py
  • front/plugins/db_cleanup/script.py
  • test/test_devices_endpoints.py
  • front/plugins/unifi_api_import/unifi_api_import.py
  • server/plugin_utils.py
  • front/plugins/website_monitor/script.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • front/plugins/dhcp_servers/script.py
🧰 Additional context used
📓 Path-based instructions (8)
front/plugins/*/script.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

front/plugins/*/script.py: Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.
During plugin processing, collect results with 'Plugin_Objects.add_object(...)' and call 'plugin_objects.write_result_file()' exactly once at the end of the script.
Do not write ad-hoc files for plugin results; only generate 'last_result..log' using 'Plugin_Objects'.
Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Files:

  • front/plugins/vendor_update/script.py
  • front/plugins/nmap_scan/script.py
  • front/plugins/internet_ip/script.py
  • front/plugins/dhcp_leases/script.py
  • front/plugins/csv_backup/script.py
  • front/plugins/internet_speedtest/script.py
  • front/plugins/luci_import/script.py
  • front/plugins/ddns_update/script.py
  • front/plugins/unifi_import/script.py
  • front/plugins/arp_scan/script.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • front/plugins/vendor_update/script.py
  • test/test_nettools_endpoints.py
  • server/scan/device_heuristics.py
  • front/plugins/icmp_scan/icmp.py
  • front/plugins/sync/sync.py
  • front/plugins/_publisher_ntfy/ntfy.py
  • front/plugins/_publisher_webhook/webhook.py
  • front/plugins/nmap_scan/script.py
  • front/plugins/plugin_helper.py
  • server/workflows/conditions.py
  • front/plugins/internet_ip/script.py
  • server/api_server/sync_endpoint.py
  • server/api_server/events_endpoint.py
  • front/plugins/__test/test.py
  • front/plugins/_publisher_pushover/pushover.py
  • front/plugins/nbtscan_scan/nbtscan.py
  • server/plugin.py
  • front/plugins/omada_sdn_imp/omada_sdn.py
  • server/workflows/app_events.py
  • test/test_history_endpoints.py
  • server/scan/session_events.py
  • front/plugins/nmap_dev_scan/nmap_dev.py
  • server/workflows/manager.py
  • front/plugins/dhcp_leases/script.py
  • server/messaging/reporting.py
  • server/logger.py
  • front/plugins/_publisher_apprise/apprise.py
  • front/plugins/_publisher_pushsafer/pushsafer.py
  • front/plugins/_publisher_mqtt/mqtt.py
  • front/plugins/wake_on_lan/wake_on_lan.py
  • test/test_graphq_endpoints.py
  • front/plugins/csv_backup/script.py
  • front/plugins/_publisher_email/email_smtp.py
  • front/plugins/freebox/freebox.py
  • server/initialise.py
  • server/api_server/api_server_start.py
  • front/plugins/internet_speedtest/script.py
  • server/helper.py
  • test/test_sessions_endpoints.py
  • front/plugins/luci_import/script.py
  • test/test_dbquery_endpoints.py
  • server/workflows/actions.py
  • test/test_device_endpoints.py
  • server/workflows/triggers.py
  • server/api_server/sessions_endpoint.py
  • server/models/notification_instance.py
  • server/api_server/device_endpoint.py
  • front/plugins/dig_scan/digscan.py
  • server/scan/device_handling.py
  • front/plugins/_publisher_telegram/tg.py
  • front/plugins/maintenance/maintenance.py
  • front/plugins/ddns_update/script.py
  • test/test_settings_endpoints.py
  • front/plugins/__template/rename_me.py
  • server/app_state.py
  • server/messaging/in_app.py
  • front/plugins/nslookup_scan/nslookup.py
  • front/plugins/unifi_import/script.py
  • front/plugins/arp_scan/script.py
test/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Tests must reside under 'test/' and use pytest.

Files:

  • test/test_nettools_endpoints.py
  • test/test_history_endpoints.py
  • test/test_graphq_endpoints.py
  • test/test_sessions_endpoints.py
  • test/test_dbquery_endpoints.py
  • test/test_device_endpoints.py
  • test/test_settings_endpoints.py
front/plugins/plugin_helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Files:

  • front/plugins/plugin_helper.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/sync_endpoint.py
  • server/api_server/events_endpoint.py
  • server/api_server/api_server_start.py
  • server/api_server/sessions_endpoint.py
  • server/api_server/device_endpoint.py
server/initialise.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add or modify settings centrally via 'ccd()' in 'server/initialise.py' or via plugin manifest; never hardcode ports or secrets—always use 'get_setting_value()'.

Files:

  • server/initialise.py
server/api_server/api_server_start.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Files:

  • server/api_server/api_server_start.py
server/helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Files:

  • server/helper.py
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/plugin_helper.py : Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Applied to files:

  • front/plugins/vendor_update/script.py
  • front/plugins/icmp_scan/icmp.py
  • front/plugins/internet_ip/script.py
  • front/plugins/__test/test.py
  • front/plugins/_publisher_pushover/pushover.py
  • front/plugins/nmap_dev_scan/nmap_dev.py
  • front/plugins/dhcp_leases/script.py
  • front/plugins/_publisher_mqtt/mqtt.py
  • front/plugins/csv_backup/script.py
  • front/plugins/internet_speedtest/script.py
  • front/plugins/luci_import/script.py
  • front/plugins/maintenance/maintenance.py
  • front/plugins/ddns_update/script.py
  • front/plugins/nslookup_scan/nslookup.py
  • front/plugins/unifi_import/script.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • front/plugins/vendor_update/script.py
  • server/scan/device_heuristics.py
  • front/plugins/icmp_scan/icmp.py
  • front/plugins/_publisher_ntfy/ntfy.py
  • server/plugin.py
  • server/workflows/app_events.py
  • front/plugins/nmap_dev_scan/nmap_dev.py
  • server/helper.py
  • server/api_server/sessions_endpoint.py
  • server/models/notification_instance.py
  • server/api_server/device_endpoint.py
  • server/app_state.py
  • front/plugins/unifi_import/script.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.

Applied to files:

  • test/test_nettools_endpoints.py
  • server/api_server/events_endpoint.py
  • test/test_history_endpoints.py
  • test/test_graphq_endpoints.py
  • test/test_sessions_endpoints.py
  • test/test_dbquery_endpoints.py
  • test/test_device_endpoints.py
  • server/api_server/sessions_endpoint.py
  • test/test_settings_endpoints.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Applied to files:

  • front/plugins/sync/sync.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : During plugin processing, collect results with 'Plugin_Objects.add_object(...)' and call 'plugin_objects.write_result_file()' exactly once at the end of the script.

Applied to files:

  • front/plugins/_publisher_webhook/webhook.py
📚 Learning: 2025-09-15T19:45:46.725Z
Learnt from: ingoratsdorf
Repo: jokob-sk/NetAlertX PR: 1176
File: server/__main__.py:191-193
Timestamp: 2025-09-15T19:45:46.725Z
Learning: The method clearPluginObjects() in server/models/notification_instance.py should be renamed to clearPluginEvents() since it deletes from the Plugins_Events table, not a Plugins_Objects table. The method name should reflect the actual table being cleared.

Applied to files:

  • front/plugins/_publisher_pushover/pushover.py
📚 Learning: 2025-11-02T02:22:10.949Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1261
File: server/app_state.py:106-115
Timestamp: 2025-11-02T02:22:10.949Z
Learning: In server/app_state.py, the pluginsStates parameter always contains complete plugin state objects with the structure: {"PLUGIN_NAME": {"lastChanged": "...", "totalObjects": N, "newObjects": N, "changedObjects": N}}. Type validation before calling .update() is not needed as the maintainer guarantees well-formed objects are always supplied.

Applied to files:

  • server/plugin.py
  • server/app_state.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/database.py : Leverage helpers in 'server/database.py' and 'server/db/*' for persistent state with SQLite.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/db/*.py : Prefer using functions from 'server/db/db_helper.py' (like 'get_table_json' and device condition helpers) over raw SQL for new database code.

Applied to files:

  • server/helper.py
  • server/api_server/device_endpoint.py
🧬 Code graph analysis (59)
front/plugins/vendor_update/script.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
test/test_nettools_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/scan/device_heuristics.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/icmp_scan/icmp.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/sync/sync.py (2)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
server/messaging/in_app.py (1)
  • write_notification (28-78)
front/plugins/_publisher_ntfy/ntfy.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/_publisher_webhook/webhook.py (1)
server/helper.py (1)
  • timeNowDB (49-64)
front/plugins/nmap_scan/script.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/plugin_helper.py (1)
server/logger.py (3)
  • mylog (103-109)
  • Logger (72-113)
  • timeNowDB (22-37)
server/workflows/conditions.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/internet_ip/script.py (2)
server/helper.py (1)
  • timeNowDB (49-64)
server/logger.py (2)
  • timeNowDB (22-37)
  • append_line_to_file (167-175)
server/api_server/sync_endpoint.py (2)
server/helper.py (1)
  • timeNowDB (49-64)
server/messaging/in_app.py (1)
  • write_notification (28-78)
server/api_server/events_endpoint.py (2)
server/helper.py (1)
  • ensure_datetime (90-95)
server/logger.py (1)
  • mylog (103-109)
front/plugins/__test/test.py (1)
server/helper.py (3)
  • get_setting_value (343-396)
  • bytes_to_string (588-592)
  • sanitize_string (627-631)
front/plugins/_publisher_pushover/pushover.py (1)
server/helper.py (3)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
  • hide_string (612-616)
front/plugins/nbtscan_scan/nbtscan.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/plugin.py (2)
server/helper.py (1)
  • timeNowDB (49-64)
server/messaging/in_app.py (1)
  • write_notification (28-78)
front/plugins/omada_sdn_imp/omada_sdn.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/workflows/app_events.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
test/test_history_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/scan/session_events.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/nmap_dev_scan/nmap_dev.py (1)
server/helper.py (4)
  • get_setting_value (343-396)
  • extract_between_strings (578-584)
  • extract_ip_addresses (685-688)
  • extract_mac_addresses (679-682)
server/workflows/manager.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/dhcp_leases/script.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/messaging/reporting.py (2)
server/helper.py (4)
  • get_file_content (240-246)
  • write_file (249-270)
  • get_timezone_offset (43-47)
  • get_setting_value (343-396)
server/logger.py (1)
  • mylog (103-109)
server/logger.py (2)
server/helper.py (1)
  • timeNowDB (49-64)
front/js/common.js (1)
  • tz (375-375)
front/plugins/_publisher_apprise/apprise.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/_publisher_pushsafer/pushsafer.py (1)
server/helper.py (3)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
  • hide_string (612-616)
front/plugins/_publisher_mqtt/mqtt.py (1)
server/helper.py (3)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
  • bytes_to_string (588-592)
front/plugins/wake_on_lan/wake_on_lan.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
test/test_graphq_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/csv_backup/script.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/_publisher_email/email_smtp.py (1)
server/helper.py (1)
  • timeNowDB (49-64)
front/plugins/freebox/freebox.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/initialise.py (2)
server/helper.py (1)
  • timeNowDB (49-64)
server/messaging/in_app.py (1)
  • write_notification (28-78)
server/api_server/api_server_start.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/internet_speedtest/script.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
server/helper.py (2)
server/logger.py (1)
  • timeNowDB (22-37)
front/js/common.js (1)
  • tz (375-375)
test/test_sessions_endpoints.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/luci_import/script.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
test/test_dbquery_endpoints.py (1)
server/helper.py (1)
  • timeNowDB (49-64)
server/workflows/actions.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
test/test_device_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/workflows/triggers.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/api_server/sessions_endpoint.py (2)
server/helper.py (9)
  • is_random_mac (649-664)
  • is_random_mac (692-703)
  • format_date (111-120)
  • get_setting_value (343-396)
  • format_date_iso (72-77)
  • format_event_date (80-87)
  • format_date_diff (122-163)
  • format_ip_long (714-725)
  • parse_datetime (98-109)
server/logger.py (1)
  • mylog (103-109)
server/models/notification_instance.py (1)
server/helper.py (1)
  • timeNowDB (49-64)
server/api_server/device_endpoint.py (1)
server/helper.py (3)
  • format_date (111-120)
  • get_setting_value (343-396)
  • timeNowDB (49-64)
front/plugins/dig_scan/digscan.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/scan/device_handling.py (1)
server/helper.py (4)
  • timeNowDB (49-64)
  • timeNowTZ (34-38)
  • get_setting_value (343-396)
  • check_IP_format (551-566)
front/plugins/_publisher_telegram/tg.py (1)
server/helper.py (2)
  • timeNowDB (49-64)
  • get_setting_value (343-396)
front/plugins/maintenance/maintenance.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/ddns_update/script.py (1)
server/helper.py (2)
  • get_setting_value (343-396)
  • check_IP_format (551-566)
test/test_settings_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/__template/rename_me.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
server/app_state.py (1)
server/helper.py (3)
  • timeNowDB (49-64)
  • timeNow (40-41)
  • checkNewVersion (797-833)
server/messaging/in_app.py (1)
server/helper.py (5)
  • timeNowDB (49-64)
  • get_file_content (240-246)
  • write_file (249-270)
  • get_setting_value (343-396)
  • get_timezone_offset (43-47)
front/plugins/nslookup_scan/nslookup.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
front/plugins/unifi_import/script.py (1)
server/helper.py (2)
  • get_setting_value (343-396)
  • normalize_string (636-642)
front/plugins/arp_scan/script.py (1)
server/helper.py (1)
  • get_setting_value (343-396)
🪛 Ruff (0.14.3)
front/plugins/_publisher_pushover/pushover.py

14-14: Unused noqa directive (non-enabled: E402)

Remove unused noqa directive

(RUF100)

server/logger.py

32-32: ZoneInfo may be undefined, or defined from star imports

(F405)


33-33: Do not catch blind exception: Exception

(BLE001)

server/initialise.py

395-395: f-string without any placeholders

Remove extraneous f prefix

(F541)

server/helper.py

59-59: ZoneInfo may be undefined, or defined from star imports

(F405)


60-60: Do not catch blind exception: Exception

(BLE001)


119-119: Do not catch blind exception: Exception

(BLE001)

server/scan/device_handling.py

559-559: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (57)
front/plugins/maintenance/maintenance.py (1)

20-20: LGTM! Unused import removed.

The removal of timeNowTZ from the import statement is appropriate since it's not used anywhere in this file. This cleanup aligns with the PR's broader objective to centralize time handling.

front/plugins/ddns_update/script.py (2)

22-22: LGTM! Correctly removes unused import.

The removal of timeNowTZ is appropriate since it's not used anywhere in this file.


93-105: Clarify plugin result tracking requirements.

The commented-out code suggests this plugin previously tracked results via Plugin_Objects. Per the coding guidelines, plugin scripts should "collect results with Plugin_Objects.add_object(...) and call plugin_objects.write_result_file() exactly once at the end of the script."

Should this DDNS plugin write result files, or is it intentionally exempt from this requirement since it performs operational tasks (DDNS updates) rather than device/object discovery?

As per coding guidelines.

front/plugins/__test/test.py (1)

26-26: LGTM! Correct removal of unused import.

The removal of timeNowTZ from the import statement is appropriate since it's not used anywhere in this test file. This aligns with the PR's objective to migrate from timeNowTZ to timeNowDB across the codebase.

front/plugins/nmap_dev_scan/nmap_dev.py (1)

24-24: LGTM!

The removal of timeNowTZ from the import is correct, as the file does not perform any timestamp operations.

front/plugins/unifi_import/script.py (1)

24-24: LGTM! Import cleanup and normalization improvement.

The removal of the unused timeNowTZ import and the addition of normalize_string aligns with the PR's migration to timeNowDB and improves string handling by using the helper utility at line 197. Based on learnings.

front/plugins/wake_on_lan/wake_on_lan.py (1)

19-19: LGTM! Appropriate cleanup of unused import.

The removal of the unused timeNowTZ import is correct and aligns with the PR's migration strategy.

front/plugins/freebox/freebox.py (1)

27-27: LGTM! Unused import removed.

Correct removal of the unused timeNowTZ import, consistent with the broader refactoring effort.

front/plugins/nmap_scan/script.py (2)

17-17: LGTM! Correct import migration to timeNowDB.

The import change from timeNowTZ to timeNowDB is appropriate and aligns with the PR's objective to use ISO-formatted, DB-friendly timestamps. Based on learnings.


161-161: LGTM! Correct usage of timeNowDB.

The replacement of timeNowTZ() with timeNowDB() for the timestamp field ensures DB-compatible ISO 8601 formatting, consistent with the broader migration pattern.

front/plugins/luci_import/script.py (1)

12-12: LGTM! Unused import removed.

Appropriate removal of the unused timeNowTZ import.

front/plugins/vendor_update/script.py (1)

20-20: LGTM! Unused import removed.

Correct cleanup of the unused timeNowTZ import.

front/plugins/nbtscan_scan/nbtscan.py (1)

18-18: LGTM! Unused import removed.

Appropriate removal of the unused timeNowTZ import.

server/scan/session_events.py (3)

9-9: LGTM! Correct import migration.

The import change from timeNowTZ to timeNowDB is appropriate for the timestamp operations in this module. Based on learnings.


131-131: LGTM! Correct usage of timeNowDB for event timestamps.

The replacement of timeNowTZ() with timeNowDB() ensures the startTime used in event insertion (lines 138, 151, 168, 182) is in ISO 8601 format, which is DB-safe and consistent with the migration pattern.


194-194: LGTM! Correct usage of timeNowDB for history timestamps.

The replacement of timeNowTZ() with timeNowDB() for scanTimestamp ensures the Online_History table receives properly formatted ISO 8601 timestamps, maintaining DB compatibility.

front/plugins/omada_sdn_imp/omada_sdn.py (1)

47-47: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file.

front/plugins/dhcp_leases/script.py (1)

18-18: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file.

front/plugins/csv_backup/script.py (1)

19-19: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file.

front/plugins/arp_scan/script.py (1)

19-19: LGTM: Unused imports removed.

The removal of timeNowTZ and strftime is appropriate as they're not used anywhere in this file.

server/api_server/sessions_endpoint.py (1)

19-19: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file. The file already imports other necessary date/time formatting functions like format_date, format_date_iso, and parse_datetime.

server/workflows/app_events.py (1)

13-13: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file. Timestamps are handled by SQLite's DATETIME('now') function.

server/workflows/manager.py (1)

12-12: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file.

front/plugins/icmp_scan/icmp.py (1)

23-23: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate as it's not used anywhere in this file.

test/test_nettools_endpoints.py (1)

13-13: LGTM: Import cleanup is appropriate.

The removal of timeNowTZ from imports is correct since the file only uses get_setting_value and does not require timestamp functionality.

front/plugins/_publisher_pushsafer/pushsafer.py (2)

22-22: LGTM: Import updated correctly.

The replacement of timeNowTZ with timeNowDB in imports aligns with the PR's standardization effort.


71-71: LGTM: Timestamp function updated correctly.

The change from timeNowTZ() to timeNowDB() provides DB-friendly ISO 8601 timestamps for the notification log's secondaryId field, consistent with the PR's objective.

front/plugins/nslookup_scan/nslookup.py (1)

23-23: LGTM: Unused import removed.

The removal of timeNowTZ is appropriate since the file only requires get_setting_value for configuration access and does not use timestamp functions.

front/plugins/dig_scan/digscan.py (1)

18-18: LGTM: Unused import removed.

The removal of timeNowTZ is correct as the file does not use timestamp functionality.

front/plugins/_publisher_mqtt/mqtt.py (1)

26-26: LGTM: Import updated correctly.

The replacement of timeNowTZ with timeNowDB aligns with the PR's standardization effort.

front/plugins/__template/rename_me.py (1)

18-18: LGTM: Template import cleanup.

The removal of timeNowTZ from the plugin template is appropriate since timestamp functionality is not needed in the template skeleton.

server/api_server/events_endpoint.py (1)

17-17: LGTM: Unused import removed.

The removal of timeNowTZ is correct since the file relies on ensure_datetime for timestamp handling, which internally uses timeNowDB() when needed.

test/test_dbquery_endpoints.py (2)

9-9: LGTM: Import updated correctly.

The replacement of timeNowTZ with timeNowDB aligns with the PR's standardization effort.


44-48: LGTM: Improved timestamp consistency.

Caching the timestamp in the now variable and using it for both devFirstConnection and devLastConnection ensures consistent timestamps for test device creation, which is appropriate for unit testing.

server/app_state.py (1)

7-7: LGTM: Timestamp migration to timeNowDB.

The import and usage changes correctly migrate from timeNowTZ() to timeNowDB() for database-friendly timestamps. The lastUpdated field now uses ISO 8601 format suitable for DB storage.

Also applies to: 62-62

front/plugins/sync/sync.py (1)

21-21: LGTM: Consistent migration to timeNowDB.

All timestamp generation for notifications and logging has been consistently migrated from timeNowTZ() to timeNowDB(), ensuring DB-friendly ISO 8601 format throughout.

Also applies to: 152-152, 258-258, 302-302, 311-311, 335-335, 343-343

server/helper.py (1)

90-95: LGTM: Updated ensure_datetime to use timeNowDB.

The function now correctly delegates to timeNowDB() when dt is None, maintaining consistency with the new timestamp standard.

server/workflows/actions.py (1)

10-10: LGTM: Removed unused import.

The timeNowTZ import was not used in this file and has been correctly removed.

server/scan/device_heuristics.py (1)

15-15: LGTM: Removed unused import.

The timeNowTZ import was not used in this file and has been correctly removed.

front/plugins/_publisher_ntfy/ntfy.py (1)

22-22: LGTM: Plugin timestamp migrated to timeNowDB.

The plugin object's secondaryId timestamp now uses timeNowDB() for DB-friendly ISO 8601 format, consistent with the repository-wide migration.

Also applies to: 71-71

server/workflows/conditions.py (1)

11-11: LGTM: Removed unused import.

The timeNowTZ import was not used in this file and has been correctly removed.

server/workflows/triggers.py (1)

10-10: LGTM! Unused import removed.

The removal of timeNowTZ is correct as it's not used anywhere in this file.

front/plugins/internet_speedtest/script.py (1)

16-16: LGTM! Consistent migration to timeNowDB.

The import and usage have been correctly updated to use timeNowDB(), which provides DB-friendly ISO 8601 timestamps for the speedtest result's secondaryId.

Also applies to: 43-43

server/models/notification_instance.py (1)

19-19: LGTM! Timestamp generation migrated to timeNowDB.

All timestamp assignments (DateTimeCreated, report date, DateTimePushed, and SQL updates) now correctly use timeNowDB() for consistent DB-friendly formatting.

Also applies to: 75-75, 116-116, 235-235, 286-286

server/scan/device_handling.py (2)

59-59: LGTM! Consistent DB timestamp generation.

The startTime assignments in both update_devices_data_from_scan and create_new_devices now correctly use timeNowDB() for DB-friendly timestamps.

Also applies to: 374-374


532-543: LGTM! Timestamp normalization handles string-to-datetime conversion.

The code correctly normalizes last_checked from string (persisted from previous run via timeNowDB() on line 676) to datetime object (lines 536-543), ensuring type consistency for comparison on line 575.

Also applies to: 676-676

front/plugins/_publisher_webhook/webhook.py (1)

25-25: LGTM! Publisher timestamp migrated to timeNowDB.

The import and usage correctly updated to use timeNowDB() for the notification log's secondaryId, consistent with other publisher plugins in this PR.

Also applies to: 74-74

test/test_device_endpoints.py (1)

12-12: LGTM! Unused import removed.

The removal of timeNowTZ is correct as it's not used in this test file.

front/plugins/plugin_helper.py (1)

14-14: LGTM! Centralized timestamp generation for plugin objects.

The migration from inline datetime.now().strftime() to timeNowDB() centralizes timestamp generation and ensures consistent timezone-aware formatting across all plugin objects.

Also applies to: 207-207

test/test_history_endpoints.py (1)

12-12: LGTM! Unused import removed.

The removal of timeNowTZ is correct as it's not used in this test file.

front/plugins/internet_ip/script.py (1)

23-23: LGTM! Timestamp standardization to timeNowDB.

The import and usage have been correctly updated to use timeNowDB() for ISO 8601 DB-friendly timestamps.

Also applies to: 83-83

server/api_server/api_server_start.py (1)

12-12: LGTM! Unused import removed.

Correctly removes timeNowTZ from imports as it's not used in this file.

test/test_settings_endpoints.py (1)

13-13: LGTM! Unused import removed.

Correctly removes timeNowTZ from imports as it's not used in this test file.

front/plugins/_publisher_apprise/apprise.py (1)

19-19: LGTM! Timestamp standardization to timeNowDB.

The import and usage in add_object have been correctly updated to use timeNowDB() for consistent ISO 8601 timestamps.

Also applies to: 68-68

server/messaging/in_app.py (1)

23-23: LGTM! Timestamp standardization to timeNowDB.

The import and default timestamp in write_notification have been correctly updated to use timeNowDB().

Also applies to: 42-42

front/plugins/_publisher_pushover/pushover.py (1)

14-14: LGTM! Timestamp standardization to timeNowDB.

The import and usage have been correctly updated to use timeNowDB() for consistent ISO 8601 timestamps.

Also applies to: 66-66

test/test_graphq_endpoints.py (1)

13-13: LGTM! Unused import removed.

Correctly removes timeNowTZ from imports as it's not used in this test file.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
server/helper.py (1)

49-69: Missing ZoneInfo import causes NameError.

The function uses ZoneInfo at line 62, but it's not imported. Additionally, datetime.UTC at line 69 doesn't exist in Python 3.10 and earlier—use datetime.timezone.utc instead.

Apply this diff to fix both issues:

 import datetime
+from zoneinfo import ZoneInfo
 import os
     else:
-        return datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d %H:%M:%S')
+        return datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
server/logger.py (1)

22-42: Missing ZoneInfo import and incorrect datetime.UTC usage.

This function has the same issues as server/helper.py:

  1. ZoneInfo is used at line 35 but not imported
  2. datetime.UTC at line 42 doesn't exist in Python ≤3.10—use datetime.timezone.utc instead

Apply this diff:

 import logging
+from zoneinfo import ZoneInfo
     else:
-        return datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d %H:%M:%S')
+        return datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
🧹 Nitpick comments (2)
server/helper.py (1)

116-125: Avoid bare Exception catch.

Catching all exceptions can hide bugs. Consider catching specific exceptions like (ValueError, AttributeError, TypeError) that you expect from date parsing.

Apply this diff:

     try:
         dt = parse_datetime(date_str)
         if dt.tzinfo is None:
             # Set timezone if missing — change to timezone.utc if you prefer UTC
             now = datetime.datetime.now(conf.tz)
             dt = dt.replace(tzinfo=now.astimezone().tzinfo)
         return dt.astimezone().isoformat()
-    except Exception:
+    except (ValueError, AttributeError, TypeError):
         return "invalid"
server/logger.py (1)

22-42: Consider extracting to shared module to avoid duplication.

timeNowDB is duplicated here and in server/helper.py. While the comment at line 14 notes this is intentional to avoid circular imports, maintaining two identical copies creates a maintenance burden. Consider extracting time utilities to a dedicated module (e.g., time_utils.py) that both helper.py and logger.py can import.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59477e7 and dc4da5b.

📒 Files selected for processing (3)
  • server/helper.py (3 hunks)
  • server/logger.py (1 hunks)
  • test/test_sessions_endpoints.py (6 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • test/test_sessions_endpoints.py
  • server/logger.py
  • server/helper.py
test/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Tests must reside under 'test/' and use pytest.

Files:

  • test/test_sessions_endpoints.py
server/helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Files:

  • server/helper.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.

Applied to files:

  • test/test_sessions_endpoints.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/helper.py
🧬 Code graph analysis (3)
test/test_sessions_endpoints.py (1)
server/helper.py (3)
  • timeNowDB (49-69)
  • timeNowTZ (34-38)
  • get_setting_value (348-401)
server/logger.py (2)
server/helper.py (1)
  • timeNowDB (49-69)
front/js/common.js (1)
  • tz (375-375)
server/helper.py (2)
server/logger.py (1)
  • timeNowDB (22-42)
front/js/common.js (1)
  • tz (375-375)
🪛 Ruff (0.14.3)
server/logger.py

35-35: ZoneInfo may be undefined, or defined from star imports

(F405)


38-38: Do not catch blind exception: Exception

(BLE001)

server/helper.py

62-62: ZoneInfo may be undefined, or defined from star imports

(F405)


65-65: Do not catch blind exception: Exception

(BLE001)


124-124: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (2)
test/test_sessions_endpoints.py (2)

13-13: LGTM! Import statement is now complete.

Both timeNowDB and timeNowTZ are correctly imported. The file uses timeNowDB() for database-friendly timestamps in test payloads and timeNowTZ() for datetime arithmetic in the calendar test (line 191). This is the correct pattern.


51-51: Consistent migration to timeNowDB() for test payloads.

The test payloads now use timeNowDB() to generate database-friendly timestamp strings for the start_time field. This aligns with the PR's objective of centralizing DB-safe timestamp formatting across the codebase.

Also applies to: 66-66, 83-83, 118-118, 166-166

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
server/helper.py (1)

117-126: Consider simplifying timezone application.

The current approach creates a temporary now datetime to extract timezone info (lines 122-123). This could be more direct:

     try:
         dt = parse_datetime(date_str)
         if dt.tzinfo is None:
-            # Set timezone if missing — change to timezone.utc if you prefer UTC
-            now = datetime.datetime.now(conf.tz)
-            dt = dt.replace(tzinfo=now.astimezone().tzinfo)
+            # Set timezone if missing
+            dt = dt.replace(tzinfo=conf.tz if isinstance(conf.tz, datetime.tzinfo) else ZoneInfo(conf.tz))
         return dt.astimezone().isoformat()
     except Exception:
         return "invalid"

Note: The current implementation is safe and handles edge cases. This is an optional refinement.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea8cea1 and 746f1a8.

📒 Files selected for processing (4)
  • docs/NOTIFICATIONS.md (1 hunks)
  • front/plugins/notification_processing/config.json (1 hunks)
  • server/helper.py (5 hunks)
  • server/scan/name_resolution.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • front/plugins/notification_processing/config.json
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/scan/name_resolution.py
  • server/helper.py
server/helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Files:

  • server/helper.py
🧠 Learnings (1)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/helper.py
🧬 Code graph analysis (2)
server/scan/name_resolution.py (1)
server/logger.py (1)
  • mylog (109-115)
server/helper.py (2)
server/logger.py (1)
  • timeNowDB (23-43)
front/js/common.js (1)
  • tz (375-375)
🪛 LanguageTool
docs/NOTIFICATIONS.md

[style] ~54-~54: Consider using a different adverb to strengthen your wording.
Context: ...IFICATIONS/NEWDEV_ignores.png) You can completely ignore detected devices globally. This ...

(COMPLETELY_ENTIRELY)


[grammar] ~61-~61: Ensure spelling is correct
Context: ...to ignore new device notifications of a certian pattern. 1. Events Filter (`NTFPRCS_ev...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 Ruff (0.14.3)
server/helper.py

66-66: Do not catch blind exception: Exception

(BLE001)


125-125: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (6)
server/scan/name_resolution.py (1)

75-75: LGTM! Helpful debugging enhancement.

The trace log appropriately shows the complete list of regex patterns before they're applied, making it easier to debug name cleanup issues. The logging level and format are consistent with the existing trace logs in this method.

docs/NOTIFICATIONS.md (2)

50-50: Verify the emoji swap is intentional.

The heading emoji for "Ignoring devices" changes from 🔕 (bell) to 💻 (laptop), while the new section "Ignoring notifications" uses the bell emoji instead. This semantic shift is sensible—notifications logically map to the bell, devices to the laptop—but represents a significant heading reorganization. Confirm this aligns with your documentation structure intent.


59-64: Documentation structure for new notifications filtering looks good.

The new "Ignoring notifications 🔕" section clearly documents the two global notification filters (NTFPRCS_event_condition and NTFPRCS_new_dev_condition). The placement after "Ignoring devices" and the distinction between filtering devices (preventing detection) versus filtering notifications (post-detection logs/alerts) is logical and helpful.

server/helper.py (3)

15-15: LGTM! Import issue resolved.

The missing ZoneInfo import has been properly added, resolving the NameError that would occur in timeNowDB() when local=True.


384-386: LGTM! Effective caching optimization.

The addition of SETTINGS_SECONDARYCACHE storage at line 385 properly caches settings retrieved from conf.mySettings, complementing the existing cache at line 402 for JSON-sourced settings. This reduces repeated lookups and improves performance.


472-473: LGTM! Ensures transformers run for array values.

The addition ensures that transformers (e.g., base64 decoding) are consistently applied to array entries, aligning with how transformers are handled for other data types (strings, objects). This fixes a gap where select-type arrays might have skipped transformation.

server/helper.py Outdated
Comment on lines 50 to 71
def timeNowDB(local=True):
"""
Return the current time (local or UTC) as ISO 8601 for DB storage.
Safe for SQLite, PostgreSQL, etc.

Example local: '2025-11-04 18:09:11'
Example UTC: '2025-11-04 07:09:11'
"""
if local:
try:
if isinstance(conf.tz, datetime.tzinfo):
tz = conf.tz
elif conf.tz:
tz = ZoneInfo(conf.tz)
else:
tz = None
except Exception:
tz = None
return datetime.datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')
else:
return datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d %H:%M:%S')

Copy link
Contributor

@coderabbitai coderabbitai bot Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Remove duplicate implementation in logger.py.

The timeNowDB function is duplicated in both server/helper.py (lines 50-71) and server/logger.py (lines 22-42). This violates DRY principles and creates a maintenance burden where bug fixes must be applied in two places.

Since the coding guidelines specify that helper.py should be used for all time operations, remove the duplicate from logger.py and import it from here instead:

In server/logger.py, replace the duplicate function with an import:

from helper import timeNowDB

Based on coding guidelines.

🧰 Tools
🪛 Ruff (0.14.3)

66-66: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In server/logger.py around lines 22 to 42, remove the duplicate timeNowDB
implementation and replace it with a single import from server/helper.py; delete
the function body in logger.py and add an import (use a package-relative import,
e.g. from .helper import timeNowDB) at the top of logger.py so all code uses the
centralized helper.timeNowDB; ensure any local references/namespace usage remain
correct after the import.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done on purpose to prevent circular references - should I create another module instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jokob-sk, that's a valid concern! You're right that importing timeNowDB from helper.py into logger.py would create a circular dependency since helper.py already imports mylog and logResult from logger.py.

Your current approach (keeping the duplicate) is a pragmatic solution given the circular import constraint. However, if you'd like to eliminate the duplication while avoiding circular imports, creating a separate module would be a cleaner architectural solution.

You could create a new module like server/time_utils.py containing just the time-related utilities (timeNowDB, timeNowTZ, timeNow, etc.) that both helper.py and logger.py can import from without creating circular dependencies.

Options:

  1. Keep current approach - Duplicate remains, but it's simple and works
  2. Create server/time_utils.py - Move time functions there, both modules import from it (eliminates duplication, cleaner separation of concerns)

Either approach is valid. The second option is more maintainable long-term if you anticipate changes to these time functions. What would you prefer?


✏️ Learnings added
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.319Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/db/*.py : Prefer using functions from 'server/db/db_helper.py' (like 'get_table_json' and device condition helpers) over raw SQL for new database code.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (1)
server/initialise.py (1)

396-396: Remove unnecessary f-string prefix.

The string literal on Line 396 uses an f prefix without any placeholders, which is unnecessary.

Apply this diff:

-        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 <i class="fa-solid fa-rotate"></i> (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', timeNowDB())
+        write_notification('[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 <i class="fa-solid fa-rotate"></i> (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', timeNowDB())
🧹 Nitpick comments (2)
front/plugins/_publisher_pushover/pushover.py (1)

14-14: Remove unused noqa directive.

The # noqa: E402 comment on line 14 is no longer needed since E402 is not enabled.

Apply this diff:

-from helper import get_setting_value, hide_string  # noqa: E402
+from helper import get_setting_value, hide_string
server/scan/device_handling.py (1)

560-561: Narrow exception handling to specific types.

Line 560 catches broad Exception. Per coding standards and static analysis, catch only the specific exceptions that parser.parse() can raise.

Apply this diff:

         elif isinstance(state_updated, str):
             try:
                 state_times.append(parser.parse(state_updated))
-            except Exception as e:
+            except (ValueError, TypeError) as e:
                 mylog('none', f'[Update Device Name] Failed to parse timestamp for {p}: {state_updated!r} ({e})')
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 746f1a8 and 286d555.

📒 Files selected for processing (38)
  • .github/copilot-instructions.md (1 hunks)
  • docs/NOTIFICATIONS.md (1 hunks)
  • front/php/components/logs.php (4 hunks)
  • front/plugins/_publisher_apprise/apprise.py (2 hunks)
  • front/plugins/_publisher_email/email_smtp.py (2 hunks)
  • front/plugins/_publisher_mqtt/mqtt.py (2 hunks)
  • front/plugins/_publisher_ntfy/ntfy.py (2 hunks)
  • front/plugins/_publisher_pushover/pushover.py (2 hunks)
  • front/plugins/_publisher_pushsafer/pushsafer.py (2 hunks)
  • front/plugins/_publisher_telegram/tg.py (2 hunks)
  • front/plugins/_publisher_webhook/webhook.py (2 hunks)
  • front/plugins/internet_ip/script.py (2 hunks)
  • front/plugins/internet_speedtest/script.py (2 hunks)
  • front/plugins/nmap_scan/script.py (2 hunks)
  • front/plugins/plugin_helper.py (2 hunks)
  • front/plugins/sync/sync.py (6 hunks)
  • server/__main__.py (1 hunks)
  • server/api.py (1 hunks)
  • server/api_server/device_endpoint.py (4 hunks)
  • server/api_server/devices_endpoint.py (1 hunks)
  • server/api_server/events_endpoint.py (1 hunks)
  • server/api_server/history_endpoint.py (1 hunks)
  • server/api_server/sessions_endpoint.py (1 hunks)
  • server/api_server/sync_endpoint.py (3 hunks)
  • server/app_state.py (3 hunks)
  • server/helper.py (3 hunks)
  • server/initialise.py (3 hunks)
  • server/logger.py (1 hunks)
  • server/messaging/in_app.py (2 hunks)
  • server/messaging/reporting.py (2 hunks)
  • server/models/notification_instance.py (5 hunks)
  • server/plugin.py (10 hunks)
  • server/scan/device_handling.py (5 hunks)
  • server/scan/session_events.py (3 hunks)
  • server/utils/datetime_utils.py (1 hunks)
  • test/api_endpoints/test_dbquery_endpoints.py (2 hunks)
  • test/api_endpoints/test_events_endpoints.py (1 hunks)
  • test/api_endpoints/test_sessions_endpoints.py (6 hunks)
✅ Files skipped from review due to trivial changes (1)
  • server/api_server/devices_endpoint.py
🚧 Files skipped from review as they are similar to previous changes (13)
  • server/models/notification_instance.py
  • front/plugins/_publisher_mqtt/mqtt.py
  • server/api_server/device_endpoint.py
  • server/messaging/reporting.py
  • server/api_server/sessions_endpoint.py
  • server/api_server/events_endpoint.py
  • server/scan/session_events.py
  • front/plugins/internet_ip/script.py
  • test/api_endpoints/test_dbquery_endpoints.py
  • front/plugins/_publisher_webhook/webhook.py
  • front/plugins/_publisher_telegram/tg.py
  • front/plugins/_publisher_ntfy/ntfy.py
  • front/plugins/internet_speedtest/script.py
🧰 Additional context used
📓 Path-based instructions (7)
front/plugins/*/script.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

front/plugins/*/script.py: Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.
During plugin processing, collect results with 'Plugin_Objects.add_object(...)' and call 'plugin_objects.write_result_file()' exactly once at the end of the script.
Do not write ad-hoc files for plugin results; only generate 'last_result..log' using 'Plugin_Objects'.
Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Files:

  • front/plugins/nmap_scan/script.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • front/plugins/nmap_scan/script.py
  • front/plugins/_publisher_pushsafer/pushsafer.py
  • server/api_server/history_endpoint.py
  • server/api.py
  • front/plugins/sync/sync.py
  • server/api_server/sync_endpoint.py
  • front/plugins/_publisher_apprise/apprise.py
  • test/api_endpoints/test_sessions_endpoints.py
  • server/__main__.py
  • front/plugins/plugin_helper.py
  • server/logger.py
  • server/utils/datetime_utils.py
  • server/app_state.py
  • server/plugin.py
  • server/messaging/in_app.py
  • test/api_endpoints/test_events_endpoints.py
  • server/helper.py
  • front/plugins/_publisher_email/email_smtp.py
  • server/scan/device_handling.py
  • front/plugins/_publisher_pushover/pushover.py
  • server/initialise.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/history_endpoint.py
  • server/api_server/sync_endpoint.py
test/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Tests must reside under 'test/' and use pytest.

Files:

  • test/api_endpoints/test_sessions_endpoints.py
  • test/api_endpoints/test_events_endpoints.py
front/plugins/plugin_helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Files:

  • front/plugins/plugin_helper.py
server/helper.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Files:

  • server/helper.py
server/initialise.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add or modify settings centrally via 'ccd()' in 'server/initialise.py' or via plugin manifest; never hardcode ports or secrets—always use 'get_setting_value()'.

Files:

  • server/initialise.py
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.319Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/db/*.py : Prefer using functions from 'server/db/db_helper.py' (like 'get_table_json' and device condition helpers) over raw SQL for new database code.
📚 Learning: 2025-11-05T04:34:52.319Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.319Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • front/plugins/nmap_scan/script.py
  • front/plugins/_publisher_pushsafer/pushsafer.py
  • server/api.py
  • front/plugins/sync/sync.py
  • server/api_server/sync_endpoint.py
  • front/plugins/_publisher_apprise/apprise.py
  • server/__main__.py
  • front/plugins/plugin_helper.py
  • server/logger.py
  • server/utils/datetime_utils.py
  • server/app_state.py
  • server/plugin.py
  • server/messaging/in_app.py
  • test/api_endpoints/test_events_endpoints.py
  • server/helper.py
  • front/plugins/_publisher_email/email_smtp.py
  • server/scan/device_handling.py
  • front/plugins/_publisher_pushover/pushover.py
  • server/initialise.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.

Applied to files:

  • server/api_server/history_endpoint.py
  • test/api_endpoints/test_events_endpoints.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/api.py
  • server/__main__.py
  • .github/copilot-instructions.md
  • server/helper.py
  • server/initialise.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Applied to files:

  • front/plugins/sync/sync.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/initialise.py : Add or modify settings centrally via 'ccd()' in 'server/initialise.py' or via plugin manifest; never hardcode ports or secrets—always use 'get_setting_value()'.

Applied to files:

  • .github/copilot-instructions.md
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/db/*.py : Prefer using functions from 'server/db/db_helper.py' (like 'get_table_json' and device condition helpers) over raw SQL for new database code.

Applied to files:

  • .github/copilot-instructions.md
  • server/helper.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: When exposing new core config, define it once using central helpers (core 'ccd()' or plugin manifest) and read it via helper functions throughout the codebase.

Applied to files:

  • .github/copilot-instructions.md
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/config.json : Add or modify plugin-specific settings only via the plugin manifest and reference via helpers, never hardcoding sensitive information.

Applied to files:

  • .github/copilot-instructions.md
📚 Learning: 2025-11-02T02:22:10.949Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1261
File: server/app_state.py:106-115
Timestamp: 2025-11-02T02:22:10.949Z
Learning: In server/app_state.py, the pluginsStates parameter always contains complete plugin state objects with the structure: {"PLUGIN_NAME": {"lastChanged": "...", "totalObjects": N, "newObjects": N, "changedObjects": N}}. Type validation before calling .update() is not needed as the maintainer guarantees well-formed objects are always supplied.

Applied to files:

  • server/app_state.py
  • server/plugin.py
📚 Learning: 2025-09-20T14:09:29.159Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/scripts/setup.sh:103-116
Timestamp: 2025-09-20T14:09:29.159Z
Learning: In NetAlertX devcontainer setup, the netalertx user has write permissions to /var/log/nginx/ directory as it's explicitly chowned to netalertx:www-data in the Dockerfile, so setup.sh can write to nginx log files without sudo.

Applied to files:

  • server/helper.py
📚 Learning: 2025-09-15T19:45:46.725Z
Learnt from: ingoratsdorf
Repo: jokob-sk/NetAlertX PR: 1176
File: server/__main__.py:191-193
Timestamp: 2025-09-15T19:45:46.725Z
Learning: The method clearPluginObjects() in server/models/notification_instance.py should be renamed to clearPluginEvents() since it deletes from the Plugins_Events table, not a Plugins_Objects table. The method name should reflect the actual table being cleared.

Applied to files:

  • front/plugins/_publisher_pushover/pushover.py
🧬 Code graph analysis (20)
front/plugins/nmap_scan/script.py (2)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
front/plugins/_publisher_pushsafer/pushsafer.py (2)
server/helper.py (2)
  • get_setting_value (210-265)
  • hide_string (481-485)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/api_server/history_endpoint.py (2)
server/helper.py (3)
  • is_random_mac (518-533)
  • is_random_mac (561-572)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • format_date (110-119)
server/api.py (2)
server/helper.py (2)
  • write_file (116-137)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowTZ (28-32)
front/plugins/sync/sync.py (3)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/messaging/in_app.py (1)
  • write_notification (29-79)
server/api_server/sync_endpoint.py (3)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/messaging/in_app.py (1)
  • write_notification (29-79)
front/plugins/_publisher_apprise/apprise.py (2)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
test/api_endpoints/test_sessions_endpoints.py (2)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (2)
  • timeNowTZ (28-32)
  • timeNowDB (43-63)
server/__main__.py (2)
server/helper.py (2)
  • filePermissions (88-100)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowTZ (28-32)
front/plugins/plugin_helper.py (1)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/logger.py (1)
server/utils/datetime_utils.py (1)
  • timeNowTZ (28-32)
server/utils/datetime_utils.py (2)
front/js/common.js (1)
  • tz (375-375)
server/helper.py (1)
  • get_setting_value (210-265)
server/app_state.py (1)
server/utils/datetime_utils.py (2)
  • timeNowDB (43-63)
  • timeNow (34-35)
server/plugin.py (3)
server/helper.py (4)
  • get_file_content (107-113)
  • write_file (116-137)
  • get_setting (149-206)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (2)
  • timeNowTZ (28-32)
  • timeNowDB (43-63)
server/messaging/in_app.py (1)
  • write_notification (29-79)
server/messaging/in_app.py (1)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
test/api_endpoints/test_events_endpoints.py (2)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowTZ (28-32)
front/plugins/_publisher_email/email_smtp.py (2)
server/helper.py (2)
  • get_setting_value (210-265)
  • hide_email (472-478)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/scan/device_handling.py (2)
server/helper.py (2)
  • get_setting_value (210-265)
  • check_IP_format (420-435)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
front/plugins/_publisher_pushover/pushover.py (2)
server/helper.py (2)
  • get_setting_value (210-265)
  • hide_string (481-485)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/initialise.py (2)
server/utils/datetime_utils.py (1)
  • timeNowDB (43-63)
server/messaging/in_app.py (1)
  • write_notification (29-79)
🪛 LanguageTool
docs/NOTIFICATIONS.md

[style] ~54-~54: Consider using a different adverb to strengthen your wording.
Context: ...IFICATIONS/NEWDEV_ignores.png) You can completely ignore detected devices globally. This ...

(COMPLETELY_ENTIRELY)

🪛 Ruff (0.14.3)
server/logger.py

17-17: from const import * used; unable to detect undefined names

(F403)

server/utils/datetime_utils.py

1-1: Shebang is present but file is not executable

(EXE001)


9-9: Redefinition of unused datetime from line 6

(F811)


21-21: from const import * used; unable to detect undefined names

(F403)


56-56: ZoneInfo may be undefined, or defined from star imports

(F405)


59-59: Do not catch blind exception: Exception

(BLE001)


118-118: Do not catch blind exception: Exception

(BLE001)


128-128: get_setting_value may be undefined, or defined from star imports

(F405)


136-136: email may be undefined, or defined from star imports

(F405)


137-137: Do not catch blind exception: Exception

(BLE001)

server/scan/device_handling.py

560-560: Do not catch blind exception: Exception

(BLE001)

front/plugins/_publisher_pushover/pushover.py

14-14: Unused noqa directive (non-enabled: E402)

Remove unused noqa directive

(RUF100)

server/initialise.py

396-396: f-string without any placeholders

Remove extraneous f prefix

(F541)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (32)
server/api.py (1)

10-11: LGTM! Import source updated correctly.

The migration of timeNowTZ from helper to utils.datetime_utils aligns with the PR's centralization of datetime utilities.

.github/copilot-instructions.md (1)

45-45: LGTM! Documentation updated to reflect new utility.

The guidance now correctly references timeNowDB as the preferred time utility from helper.py.

front/plugins/nmap_scan/script.py (2)

17-18: LGTM! Import updated correctly.

The migration to timeNowDB from utils.datetime_utils is appropriate for database timestamp generation.


162-162: LGTM! Timestamp source updated appropriately.

Using timeNowDB() here ensures the timestamp is in the correct ISO 8601 format for database storage.

front/plugins/_publisher_email/email_smtp.py (2)

28-29: LGTM! Import migration completed correctly.

The switch to timeNowDB from utils.datetime_utils aligns with the centralization effort.


90-90: LGTM! Timestamp format updated for database storage.

Using timeNowDB() for secondaryId ensures consistent ISO 8601 formatting for plugin logging.

front/php/components/logs.php (2)

18-27: LGTM! Defensive file handling added.

The addition of file existence and readability checks prevents errors and provides user-friendly feedback when files are missing or inaccessible.


31-31: LGTM! Download button guarded appropriately.

The additional file_exists($filePath) check prevents broken download links for missing files.

server/plugin.py (3)

15-16: LGTM! Import migration completed correctly.

The dual import of timeNowTZ and timeNowDB is appropriate since the module uses both: timeNowDB for database timestamps and timeNowTZ for datetime objects (e.g., schedule tracking at Line 107).


225-225: LGTM! Consistent timestamp captured at function start.

Capturing now_str = timeNowDB() at the function start ensures all stateUpdated fields use the same timestamp, which is appropriate for consistency.


763-763: LGTM! Simplified timestamp generation.

Replacing timeNowTZ().strftime(...) with timeNowDB() is cleaner and ensures consistent formatting for database storage.

front/plugins/plugin_helper.py (2)

15-15: LGTM! Import added for centralized time utility.

The import of timeNowDB from utils.datetime_utils aligns with the PR's datetime centralization effort.


208-208: LGTM! Timestamp generation simplified.

Replacing datetime.now().strftime("%Y-%m-%d %H:%M:%S") with timeNowDB() is cleaner and ensures consistent formatting across the codebase.

front/plugins/_publisher_pushsafer/pushsafer.py (1)

22-23: LGTM: Clean migration to timeNowDB.

The import and usage updates correctly standardize on timeNowDB() for logging timestamps, aligning with the broader PR refactor.

Also applies to: 72-72

front/plugins/sync/sync.py (1)

21-22: LGTM: Consistent notification timestamp migration.

All write_notification calls now correctly use timeNowDB() instead of timeNowTZ(), ensuring consistent ISO 8601 timestamps across notification logging.

Also applies to: 153-153, 259-259, 303-303, 312-312, 336-336, 344-344

front/plugins/_publisher_pushover/pushover.py (1)

14-15: LGTM: Timestamp migration correct.

The switch from timeNowTZ() to timeNowDB() is consistent with the PR's standardization effort.

Also applies to: 67-67

front/plugins/_publisher_apprise/apprise.py (1)

19-20: LGTM: Standard migration pattern.

The migration from timeNowTZ() to timeNowDB() follows the same clean pattern as other publisher plugins.

Also applies to: 69-69

server/scan/device_handling.py (2)

6-6: LGTM: Successful migration to timeNowDB.

The import updates and timeNowDB() usage for startTime and name_plugins_checked correctly standardize timestamp generation across the module.

Also applies to: 13-14, 60-60, 375-375, 677-677


533-577: Approve refactored timestamp normalization with better type safety.

The refactored update_devices_names function now properly normalizes timestamps from multiple sources (strings, datetime objects) before comparison, addressing the type mismatch issues flagged in previous reviews. The logic correctly:

  • Normalizes last_checked to datetime or None (lines 536-544)
  • Collects and validates plugin state timestamps (lines 546-572)
  • Safely computes latest_state with fallback handling (lines 565-572)
  • Compares normalized datetime objects (line 576)

This ensures type-safe comparisons and prevents TypeError exceptions.

server/messaging/in_app.py (1)

23-24: LGTM: Default timestamp correctly updated.

The migration updates the default timestamp parameter from timeNowTZ() to timeNowDB(), ensuring consistent ISO 8601 format for notification timestamps.

Also applies to: 43-43

test/api_endpoints/test_events_endpoints.py (1)

13-14: LGTM: Import path correctly updated.

The import of timeNowTZ has been correctly moved from helper to utils.datetime_utils, maintaining the same functionality while aligning with the new module structure.

server/__main__.py (1)

29-30: LGTM: Import path migration correct.

The import of timeNowTZ has been properly relocated from helper to utils.datetime_utils, maintaining the same functionality while supporting the new module structure.

server/api_server/history_endpoint.py (1)

17-18: LGTM: Clean refactor to centralized datetime utilities.

The import restructure correctly moves format_date to the new server/utils/datetime_utils module, aligning with the PR's objective to consolidate datetime handling.

test/api_endpoints/test_sessions_endpoints.py (1)

13-14: LGTM: Correct migration to centralized datetime utilities.

The imports correctly source timeNowTZ and timeNowDB from utils.datetime_utils, with appropriate usage throughout: timeNowDB() for database timestamp fields and timeNowTZ() for datetime object calculations.

server/initialise.py (1)

15-16: LGTM: Timestamp refactor correctly applied.

The import and usage updates properly migrate to timeNowDB() from the centralized utils.datetime_utils module for notification timestamps.

server/app_state.py (1)

7-8: LGTM: Correct datetime utilities migration.

The imports correctly source time functions from utils.datetime_utils, with appropriate usage: timeNowDB() for ISO timestamp strings and timeNow().timestamp() for numeric timestamps.

docs/NOTIFICATIONS.md (1)

50-64: LGTM: Clear documentation improvements.

The restructure separates "Ignoring devices" (preventing device detection) from "Ignoring notifications" (filtering notification output), improving clarity for users configuring the system.

server/logger.py (1)

8-18: LGTM: Proper migration to centralized datetime utilities.

The updates correctly import timeNowTZ from the new utils.datetime_utils module, eliminating the local duplicate definition. The ZoneInfo import and sys.path setup properly support the datetime utilities infrastructure.

server/api_server/sync_endpoint.py (1)

5-6: LGTM: Consistent timestamp refactor.

The migration to timeNowDB() from utils.datetime_utils correctly provides ISO-formatted timestamp strings for notifications and API responses.

server/helper.py (3)

245-247: LGTM: Improved caching for settings retrieval.

Adding the secondary cache update when sourcing from conf.mySettings improves performance by caching values from both retrieval paths (in-memory settings and JSON file).


250-250: LGTM: Typo correction.

Fixed spelling error in comment: "retrive" → "retrieve".


333-334: LGTM: Enhanced array transformer handling.

The unconditional transformer application to array entries (particularly base64 decoding) correctly handles encoded array values. The reverseTransformers function properly maps the transformation over list items.

Comment on lines 6 to 9
from datetime import datetime
import pytz
from pytz import timezone
import datetime
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove duplicate datetime import.

Line 6 imports datetime from the datetime module, and Line 9 imports the datetime module itself. The duplicate on Line 9 shadows the earlier import.

Apply this diff to remove the duplicate:

 from datetime import datetime
 import pytz
 from pytz import timezone, all_timezones, UnknownTimeZoneError
-import datetime
 from typing import Union

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.3)

9-9: Redefinition of unused datetime from line 6

(F811)

🤖 Prompt for AI Agents
In server/utils/datetime_utils.py around lines 6 to 9, there's a duplicate
import: you already have "from datetime import datetime" on line 6 and later
"import datetime" on line 9 which shadows the earlier name; remove the redundant
"import datetime" line (or replace with explicit aliases only if you need both
module and class) so only the correct import(s) remain and adjust any code that
relied on the module import to use the imported class or an alias.

INSTALL_PATH="/app"

import conf
from const import *
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Replace wildcard import with explicit imports.

The wildcard import from const import * makes it unclear what symbols are being used and can lead to naming conflicts.

Determine which symbols from const are actually needed (likely none based on the code) and import them explicitly. If no imports are needed, remove this line entirely:

-from const import *
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from const import *
🧰 Tools
🪛 Ruff (0.14.3)

21-21: from const import * used; unable to detect undefined names

(F403)

🤖 Prompt for AI Agents
In server/utils/datetime_utils.py around line 21, the file uses a wildcard
import "from const import *" which obscures used symbols and risks name
collisions; inspect the module to identify the specific constants or symbols
actually referenced (or determine that none are used) and replace the wildcard
with an explicit import of only those names, or remove the import line entirely
if nothing from const is required.

Comment on lines 51 to 63
if local:
try:
if isinstance(conf.tz, datetime.tzinfo):
tz = conf.tz
elif conf.tz:
tz = ZoneInfo(conf.tz)
else:
tz = None
except Exception:
tz = None
return datetime.datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')
else:
return datetime.datetime.now(datetime.UTC).strftime('%Y-%m-%d %H:%M:%S')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add missing ZoneInfo import and handle exception more specifically.

Line 56 uses ZoneInfo without importing it. Also, the bare Exception catch on Line 59 is too broad.

Apply this diff to add the import and improve exception handling:

+from zoneinfo import ZoneInfo
+
 import conf
-from const import *
 
 
 
 #-------------------------------------------------------------------------------
 # DateTime
 #-------------------------------------------------------------------------------

Then update the exception handling:

     if local:
         try:
             if isinstance(conf.tz, datetime.tzinfo):
                 tz = conf.tz
             elif conf.tz:
                 tz = ZoneInfo(conf.tz)
             else:
                 tz = None
-        except Exception:
+        except (KeyError, ValueError, TypeError):
             tz = None

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.3)

56-56: ZoneInfo may be undefined, or defined from star imports

(F405)


59-59: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In server/utils/datetime_utils.py around lines 51 to 63, add an import for
ZoneInfo from the zoneinfo module at the top of the file and replace the bare
"except Exception:" with a targeted exception handler (catch
zoneinfo.ZoneInfoNotFoundError and ValueError) when constructing
ZoneInfo(conf.tz); if those exceptions occur set tz = None. Ensure you import
ZoneInfo like "from zoneinfo import ZoneInfo" and only catch the specific errors
that can be raised by ZoneInfo creation rather than a broad Exception.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
server/utils/datetime_utils.py (3)

19-19: Replace wildcard import with explicit imports.

The wildcard import obscures which symbols from const are actually used and can cause naming conflicts.

Based on learnings.

Inspect the code to determine which symbols from const are needed, then replace with explicit imports:

-from const import *
+# Add explicit imports if needed, e.g.:
+# from const import SYMBOL_NAME

If no symbols from const are used in this module, remove the import entirely.


49-58: Handle timezone exceptions more specifically.

The bare Exception catch is too broad and may hide unexpected errors when constructing ZoneInfo.

Apply this diff to catch only the specific exceptions that ZoneInfo can raise:

         try:
             if isinstance(conf.tz, datetime.tzinfo):
                 tz = conf.tz
             elif conf.tz:
                 tz = ZoneInfo(conf.tz)
             else:
                 tz = None
-        except Exception:
+        except (KeyError, ValueError, TypeError):
             tz = None

6-7: Resolve conflicting datetime imports.

Line 6 imports the datetime class, and Line 7 imports the datetime module, causing the module import to shadow the class. Since the code uses both datetime.datetime.now() (requiring the module) and potentially direct class references, you should import both explicitly with an alias to avoid ambiguity.

Apply this diff:

-from datetime import datetime
-import datetime
+import datetime
+from datetime import datetime as dt_class

Then update code that uses the bare class name (e.g., Line 51's datetime.tzinfo) to use datetime.tzinfo, which is now unambiguous.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 286d555 and 1fd8d97.

📒 Files selected for processing (2)
  • server/api_server/sessions_endpoint.py (4 hunks)
  • server/utils/datetime_utils.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/sessions_endpoint.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/api_server/sessions_endpoint.py
  • server/utils/datetime_utils.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/db/*.py : Prefer using functions from 'server/db/db_helper.py' (like 'get_table_json' and device condition helpers) over raw SQL for new database code.
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.319Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/database.py : Leverage helpers in 'server/database.py' and 'server/db/*' for persistent state with SQLite.
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.

Applied to files:

  • server/api_server/sessions_endpoint.py
📚 Learning: 2025-11-05T04:34:52.319Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.319Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • server/utils/datetime_utils.py
🧬 Code graph analysis (2)
server/api_server/sessions_endpoint.py (4)
server/helper.py (4)
  • is_random_mac (518-533)
  • is_random_mac (561-572)
  • get_setting_value (210-265)
  • format_ip_long (583-594)
server/logger.py (1)
  • mylog (84-90)
server/db/db_helper.py (2)
  • row_to_json (47-72)
  • get_date_from_period (97-117)
server/utils/datetime_utils.py (5)
  • format_date_iso (69-74)
  • format_event_date (77-84)
  • format_date_diff (119-159)
  • parse_datetime (95-106)
  • format_date (108-117)
server/utils/datetime_utils.py (1)
front/js/common.js (1)
  • tz (375-375)
🪛 Ruff (0.14.3)
server/api_server/sessions_endpoint.py

354-354: Undefined name tz_name

(F821)


358-358: Undefined name tz_name

(F821)

server/utils/datetime_utils.py

1-1: Shebang is present but file is not executable

(EXE001)


7-7: Redefinition of unused datetime from line 6

(F811)


19-19: from const import * used; unable to detect undefined names

(F403)


57-57: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (4)
server/utils/datetime_utils.py (2)

108-117: Good exception handling improvements.

The specific exception types (ValueError, AttributeError, TypeError) are appropriate for parsing errors and provide better error visibility than a bare except Exception.


128-143: Good timezone-aware parsing with specific exception handling.

The fallback from RFC1123 to ISO format with specific exception handling (ValueError, TypeError) and timezone normalization is well-implemented.

server/api_server/sessions_endpoint.py (2)

19-21: Good refactoring to use centralized datetime utilities.

The import changes properly consolidate datetime formatting helpers into the utils.datetime_utils module, aligning with the PR objective to centralize datetime handling.


211-211: Correct timezone-aware duration calculations in get_device_sessions.

The tz_name retrieval from settings and its usage in format_date_diff calls ensures timezone-aware duration formatting.

Also applies to: 234-236

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
server/utils/datetime_utils.py (3)

57-57: Use specific exception types instead of bare Exception.

Line 57 catches a bare Exception which can hide unexpected errors. When constructing ZoneInfo(conf.tz), the specific exceptions that can be raised should be caught.

Apply this diff:

         try:
             if isinstance(conf.tz, datetime.tzinfo):
                 tz = conf.tz
             elif conf.tz:
                 tz = ZoneInfo(conf.tz)
             else:
                 tz = None
-        except Exception:
+        except (KeyError, ValueError, TypeError):
             tz = None

19-19: Replace wildcard import with explicit imports.

The wildcard import from const import * obscures which symbols are being used and can cause naming conflicts.

Determine which symbols from const are actually used in this file and import them explicitly:

-from const import *
+# Import specific symbols from const if needed, or remove if unused

Based on the code, it appears no symbols from const are directly referenced in this file, so this import may be unnecessary and should be removed.


6-7: Remove duplicate datetime import.

Line 7 imports the datetime module, but line 6 already imports datetime from the datetime module. This creates a naming conflict where the module import shadows the class import.

Apply this diff:

 from datetime import datetime
 import datetime
 import pytz

Since line 6 imports the datetime class, either:

  1. Remove line 7 if only the datetime class is needed, OR
  2. Use import datetime as dt if both module and class are needed

Based on the code usage (e.g., datetime.datetime.now(), datetime.tzinfo, datetime.UTC), you need the module. Update to:

-from datetime import datetime
-import datetime
+import datetime
🧹 Nitpick comments (2)
server/scan/device_handling.py (1)

563-563: Use idiomatic Python comparisons.

Lines 563, 569, and 592 use non-idiomatic comparisons that should be updated per PEP 8:

  • Lines 563, 569: Use is None instead of == None
  • Line 592: Use not check_plugin_data_changed(...) instead of == False

Apply this diff:

-        if last_changed_ts == None:
+        if last_changed_ts is None:
             mylog('none', f'[check_plugin_data_changed] Unexpected last_data_change timestamp for {plugin_name}: {last_data_change}')

-        if last_data_check_ts == None:
+        if last_data_check_ts is None:
             mylog('none', f'[check_plugin_data_changed] Unexpected last_data_check timestamp for {plugin_name}: {last_data_check}')
-    if check_plugin_data_changed(pm, ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]) == False:
+    if not check_plugin_data_changed(pm, ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]):
         mylog('debug', '[Update Device Name] No relevant plugin changes since last check.')
         return

Also applies to: 569-569, 592-592

docs/PLUGINS_DEV_CONFIG.md (1)

17-19: Add language specification to fenced code block.

The code block on line 17 should specify a language identifier for proper syntax highlighting and rendering.

Apply this diff:

-```
+```log
 ================ CurrentScan table content ================

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: CodeRabbit UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between cbe5a4a7327c0b96bfdd2ea9de9f678f96f59a2a and 552d2a82869b7f7c777d76c73e70b20b44a867d7.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `docs/PLUGINS_DEV_CONFIG.md` (1 hunks)
* `server/plugin.py` (11 hunks)
* `server/scan/device_handling.py` (5 hunks)
* `server/utils/datetime_utils.py` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>**/*.py</summary>


**📄 CodeRabbit inference engine (.github/copilot-instructions.md)**

> Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:
- `server/scan/device_handling.py`
- `server/plugin.py`
- `server/utils/datetime_utils.py`

</details>

</details><details>
<summary>🧠 Learnings (7)</summary>

<details>
<summary>📓 Common learnings</summary>

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.


Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, timeNowDB function is intentionally duplicated in both server/helper.py and server/logger.py to prevent circular import issues, since helper.py imports from logger.py (from logger import mylog, logResult). This duplication is by design.


</details>
<details>
<summary>📚 Learning: 2025-11-05T04:34:52.339Z</summary>

Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, timeNowDB function is intentionally duplicated in both server/helper.py and server/logger.py to prevent circular import issues, since helper.py imports from logger.py (from logger import mylog, logResult). This duplication is by design.


**Applied to files:**
- `server/scan/device_handling.py`
- `server/plugin.py`
- `server/utils/datetime_utils.py`

</details>
<details>
<summary>📚 Learning: 2025-10-21T01:40:24.597Z</summary>

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/config.json : Add or modify plugin-specific settings only via the plugin manifest and reference via helpers, never hardcoding sensitive information.


**Applied to files:**
- `docs/PLUGINS_DEV_CONFIG.md`

</details>
<details>
<summary>📚 Learning: 2025-10-21T01:40:24.597Z</summary>

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/config.json : Ensure each plugin manifest resides at 'front/plugins/<code_name>/config.json', with '<code_name>' matching the folder, and settings filenames driven by 'unique_prefix'.


**Applied to files:**
- `docs/PLUGINS_DEV_CONFIG.md`

</details>
<details>
<summary>📚 Learning: 2025-10-21T01:40:24.597Z</summary>

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: When adding a plugin, start from the provided template in 'front/plugins/__template', implement with 'plugin_helper', define all required manifest settings, and wire execution via '_RUN'.


**Applied to files:**
- `docs/PLUGINS_DEV_CONFIG.md`

</details>
<details>
<summary>📚 Learning: 2025-11-02T02:22:10.968Z</summary>

Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1261
File: server/app_state.py:106-115
Timestamp: 2025-11-02T02:22:10.968Z
Learning: In server/app_state.py, the pluginsStates parameter always contains complete plugin state objects with the structure: {"PLUGIN_NAME": {"lastChanged": "...", "totalObjects": N, "newObjects": N, "changedObjects": N}}. Type validation before calling .update() is not needed as the maintainer guarantees well-formed objects are always supplied.


**Applied to files:**
- `server/plugin.py`

</details>
<details>
<summary>📚 Learning: 2025-10-21T01:40:24.597Z</summary>

Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.


**Applied to files:**
- `server/utils/datetime_utils.py`

</details>

</details><details>
<summary>🧬 Code graph analysis (3)</summary>

<details>
<summary>server/scan/device_handling.py (5)</summary><blockquote>

<details>
<summary>server/helper.py (2)</summary>

* `get_setting_value` (210-265)
* `check_IP_format` (420-435)

</details>
<details>
<summary>server/utils/datetime_utils.py (2)</summary>

* `timeNowDB` (41-61)
* `normalizeTimeStamp` (68-105)

</details>
<details>
<summary>server/logger.py (1)</summary>

* `mylog` (84-90)

</details>
<details>
<summary>server/scan/name_resolution.py (1)</summary>

* `NameResolver` (24-84)

</details>
<details>
<summary>server/models/device_instance.py (1)</summary>

* `DeviceInstance` (12-84)

</details>

</blockquote></details>
<details>
<summary>server/plugin.py (2)</summary><blockquote>

<details>
<summary>server/utils/datetime_utils.py (2)</summary>

* `timeNowTZ` (26-30)
* `timeNowDB` (41-61)

</details>
<details>
<summary>server/messaging/in_app.py (1)</summary>

* `write_notification` (29-79)

</details>

</blockquote></details>
<details>
<summary>server/utils/datetime_utils.py (1)</summary><blockquote>

<details>
<summary>front/js/common.js (1)</summary>

* `tz` (375-375)

</details>

</blockquote></details>

</details><details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

<details>
<summary>docs/PLUGINS_DEV_CONFIG.md</summary>

17-17: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

184-184: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

</details>

</details>
<details>
<summary>🪛 Ruff (0.14.3)</summary>

<details>
<summary>server/scan/device_handling.py</summary>

563-563: Comparison to `None` should be `cond is None`

Replace with `cond is None`

(E711)

---

569-569: Comparison to `None` should be `cond is None`

Replace with `cond is None`

(E711)

---

592-592: Avoid equality comparisons to `False`; use `not ...:` for false checks

Replace comparison

(E712)

</details>
<details>
<summary>server/utils/datetime_utils.py</summary>

1-1: Shebang is present but file is not executable

(EXE001)

---

7-7: Redefinition of unused `datetime` from line 6

(F811)

---

19-19: `from const import *` used; unable to detect undefined names

(F403)

---

57-57: Do not catch blind exception: `Exception`

(BLE001)

---

100-100: `parser` may be undefined, or defined from star imports

(F405)

---

101-101: Do not catch blind exception: `Exception`

(BLE001)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)</summary>

* GitHub Check: docker_dev

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>server/scan/device_handling.py (2)</summary><blockquote>

`6-6`: **LGTM! Consistent time source migration.**

The migration from `timeNowTZ()` to `timeNowDB()` for database timestamps is well-executed and aligns with the PR's centralization of datetime utilities. The imports are clean and the usage is consistent.




Also applies to: 14-14, 60-60, 375-375

---

`589-700`: **Well-structured plugin change detection and name resolution flow.**

The integration of `check_plugin_data_changed` provides an efficient early-return optimization. The multi-strategy name resolution with structured logging and plugin timestamp tracking (line 699) is well-implemented.

</blockquote></details>
<details>
<summary>docs/PLUGINS_DEV_CONFIG.md (1)</summary><blockquote>

`1-191`: **Excellent documentation updates.**

The restructured plugin lifecycle documentation with clear flow descriptions, updated terminology (lastDataChange, Plugin Interface Contract), and well-organized plugin categories significantly improves clarity for plugin developers.

</blockquote></details>
<details>
<summary>server/utils/datetime_utils.py (1)</summary><blockquote>

`26-62`: **Well-designed centralized datetime utilities.**

The new `timeNowDB()`, `timeNowTZ()`, and `normalizeTimeStamp()` functions provide a clean, centralized approach to time handling with proper timezone support. The documentation is clear, and the fallback behavior for missing timezone configuration is appropriate.

</blockquote></details>
<details>
<summary>server/plugin.py (3)</summary><blockquote>

`15-16`: **Clean datetime utility migration and improved naming.**

The import of `timeNowTZ` and `timeNowDB` from the centralized `utils.datetime_utils` module is well-executed. The rename from `name_plugins_checked` to `plugin_checks` (line 31) provides clearer semantics for general plugin check tracking.




Also applies to: 31-31

---

`158-158`: **Consistent use of timeNowDB() for database operations.**

All database timestamp operations now use `timeNowDB()` instead of `timeNowTZ()`, ensuring consistent ISO 8601 formatted timestamps suitable for database storage. This aligns with the PR's centralization objectives.




Also applies to: 167-167, 181-181, 190-190, 225-225, 763-763

---

`216-216`: **Schema change: lastChanged → lastDataChange.**

The rename from `lastChanged` to `lastDataChange` in the plugin state structure provides clearer semantics, distinguishing data change timestamps from other state changes. This is a beneficial API improvement.




Also applies to: 241-241, 264-264

</blockquote></details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
server/utils/datetime_utils.py (4)

6-8: Remove unused datetime class import.

Line 6 imports the datetime class, but line 8 immediately shadows it by importing the datetime module. Since the code exclusively uses datetime.datetime.now(), datetime.datetime.fromisoformat(), etc. (requiring the module), line 6 serves no purpose.

Apply this diff:

-from datetime import datetime
 from dateutil import parser
 import datetime

21-21: Remove unused wildcard import.

The wildcard import from const import * obscures which symbols are imported and can cause naming conflicts. A review of this file shows no usage of symbols from const.

Apply this diff:

 import conf
-from const import *

47-68: Replace bare exception with specific exception types.

Line 63 catches Exception too broadly. When constructing ZoneInfo(conf.tz), the specific exceptions that can occur are KeyError (including ZoneInfoNotFoundError) and TypeError.

Apply this diff:

     if local:
         try:
             if isinstance(conf.tz, datetime.tzinfo):
                 tz = conf.tz
             elif conf.tz:
                 tz = ZoneInfo(conf.tz)
             else:
                 tz = None
-        except Exception:
+        except (KeyError, TypeError):
             tz = None

100-117: Replace bare exception with specific exception types.

Line 113 catches Exception too broadly. The parser.parse() call can raise ValueError, TypeError, or dateutil.parser.ParserError. Catching specific exceptions makes error handling more precise and prevents masking unexpected errors.

Apply this diff:

+from dateutil.parser import ParserError
+
         try:
             # match the "2025-11-08 14:32:10" format
             pattern = DATETIME_REGEX

             if pattern.match(inputTimeStamp):
                 return datetime.datetime.strptime(inputTimeStamp, DATETIME_PATTERN)
             else:
                 # Handles SQLite and ISO8601 automatically
                 return parser.parse(inputTimeStamp)
-        except Exception:
+        except (ValueError, TypeError, ParserError):
             return None
🧹 Nitpick comments (2)
server/scan/device_handling.py (2)

563-570: Use is None for None comparisons.

Lines 563 and 569 use == None which is not idiomatic Python. Line 573 in the same function correctly uses is None, making this inconsistent. Since None is a singleton, identity checks with is are preferred.

Apply this diff:

-        if last_changed_ts == None:
+        if last_changed_ts is None:
             mylog('none', f'[check_plugin_data_changed] Unexpected last_data_change timestamp for {plugin_name} (input|output): ({last_data_change}|{last_changed_ts})')

         # Normalize and validate last_data_check timestamp
         last_data_check_ts = normalizeTimeStamp(last_data_check)

-        if last_data_check_ts == None:
+        if last_data_check_ts is None:
             mylog('none', f'[check_plugin_data_changed] Unexpected last_data_check timestamp for {plugin_name} (input|output): ({last_data_check}|{last_data_check_ts})')

589-594: Use not instead of == False for boolean checks.

Line 592 compares a boolean return value with == False, which is not idiomatic Python. The preferred approach is to use the not operator directly.

Apply this diff:

 def update_devices_names(pm):

     # --- Short-circuit if no name-resolution plugin has changed ---
-    if check_plugin_data_changed(pm, ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]) == False:
+    if not check_plugin_data_changed(pm, ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]):
         mylog('debug', '[Update Device Name] No relevant plugin changes since last check.')
         return
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 552d2a8 and 5cf8a25.

📒 Files selected for processing (2)
  • server/scan/device_handling.py (5 hunks)
  • server/utils/datetime_utils.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/scan/device_handling.py
  • server/utils/datetime_utils.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
📚 Learning: 2025-11-05T04:34:52.339Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • server/scan/device_handling.py
  • server/utils/datetime_utils.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/utils/datetime_utils.py
🧬 Code graph analysis (2)
server/scan/device_handling.py (5)
server/helper.py (2)
  • get_setting_value (210-265)
  • check_IP_format (420-435)
server/utils/datetime_utils.py (2)
  • timeNowDB (47-67)
  • normalizeTimeStamp (74-117)
server/logger.py (1)
  • mylog (84-90)
server/scan/name_resolution.py (1)
  • NameResolver (24-84)
server/models/device_instance.py (1)
  • DeviceInstance (12-84)
server/utils/datetime_utils.py (1)
front/js/common.js (2)
  • tz (375-375)
  • match (390-390)
🪛 Ruff (0.14.3)
server/scan/device_handling.py

563-563: Comparison to None should be cond is None

Replace with cond is None

(E711)


569-569: Comparison to None should be cond is None

Replace with cond is None

(E711)


592-592: Avoid equality comparisons to False; use not ...: for false checks

Replace comparison

(E712)

server/utils/datetime_utils.py

1-1: Shebang is present but file is not executable

(EXE001)


8-8: Redefinition of unused datetime from line 6

(F811)


21-21: from const import * used; unable to detect undefined names

(F403)


63-63: Do not catch blind exception: Exception

(BLE001)


113-113: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
front/plugins/nmap_dev_scan/nmap_dev.py (1)

11-12: Remove unused imports as part of this cleanup PR.

The following imports are not used anywhere in the code and should be removed:

  • csv (line 11)
  • sqlite3 (line 12)
  • datetime (line 16)
  • DB (line 26)
  • DeviceInstance (line 27)

Since this PR focuses on refactoring and cleanup, removing these unused imports would improve code clarity.

Apply this diff to remove the unused imports:

-import csv
-import sqlite3
 import re
 import nmap  
 from io import StringIO
-from datetime import datetime

 # Register NetAlertX directories
 INSTALL_PATH="/app"
 sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])

 from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
 from logger import mylog, Logger, append_line_to_file
 from helper import get_setting_value, extract_between_strings, extract_ip_addresses, extract_mac_addresses
 from const import logPath, applicationPath, fullDbPath
-from database import DB
-from models.device_instance import DeviceInstance
 import conf
 from pytz import timezone

Also applies to: 16-16, 26-27

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cf8a25 and 68c8e16.

📒 Files selected for processing (5)
  • .github/workflows/docker_dev.yml (3 hunks)
  • .github/workflows/docker_prod.yml (2 hunks)
  • .github/workflows/docker_rewrite.yml (1 hunks)
  • front/plugins/_publisher_mqtt/mqtt.py (2 hunks)
  • front/plugins/nmap_dev_scan/nmap_dev.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • front/plugins/_publisher_mqtt/mqtt.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • front/plugins/nmap_dev_scan/nmap_dev.py
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.
📚 Learning: 2025-11-05T04:34:52.339Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • front/plugins/nmap_dev_scan/nmap_dev.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/plugin_helper.py : Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Applied to files:

  • front/plugins/nmap_dev_scan/nmap_dev.py
📚 Learning: 2025-09-20T03:01:19.912Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/Dockerfile:18-19
Timestamp: 2025-09-20T03:01:19.912Z
Learning: In the NetAlertX repository, .devcontainer/Dockerfile is auto-generated and should not be reviewed directly. Review comments about dependencies and build steps should be directed at the root Dockerfile where the actual source commands are located.

Applied to files:

  • .github/workflows/docker_dev.yml
📚 Learning: 2025-09-20T02:56:24.501Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/devcontainer.json:5-8
Timestamp: 2025-09-20T02:56:24.501Z
Learning: In the NetAlertX devcontainer setup, the final .devcontainer/Dockerfile is generated by combining the root Dockerfile with .devcontainer/resources/devcontainer-Dockerfile using the generate-dockerfile.sh script. The devcontainer.json should reference the generated file, not the root Dockerfile.

Applied to files:

  • .github/workflows/docker_dev.yml
🧬 Code graph analysis (1)
front/plugins/nmap_dev_scan/nmap_dev.py (1)
server/helper.py (4)
  • get_setting_value (210-265)
  • extract_between_strings (447-453)
  • extract_ip_addresses (554-557)
  • extract_mac_addresses (548-551)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (8)
.github/workflows/docker_rewrite.yml (1)

46-46: ✓ Docker metadata action upgraded to v5.

Line 46 upgrades docker/metadata-action@v4 to v5, resolving the critical actionlint warning about an outdated runner that was flagged in previous reviews. The upgrade is appropriate and maintains the existing tag generation logic.

.github/workflows/docker_dev.yml (3)

34-40: ✓ Timestamp-based version generation for dev builds.

Lines 34–40 introduce a new step that generates a UTC timestamp in format dev-YYYYMMDD-HHMMSS. This aligns well with the PR's datetime centralization effort and ensures each dev build gets a unique, sortable identifier. Using date -u ensures consistency across different runner timezones.


52-52: ✓ Corrected .VERSION file write operation.

Line 52 correctly switches from >> (append) to > (overwrite) when writing the timestamp version to .VERSION. This ensures the file contains exactly the intended version, not accumulated content from previous runs.


56-56: ✓ Docker metadata action upgraded to v5 with timestamp tag integration.

Line 56 upgrades to docker/metadata-action@v5, resolving the critical actionlint warning. Line 63 integrates the timestamp version as a raw tag, ensuring dev image tags include the build timestamp for easy identification and traceability.

Also applies to: 63-63

.github/workflows/docker_prod.yml (3)

35-42: ✓ Release tag–based versioning with proper extraction.

Lines 35–38 extract the version from the git tag using the standard GITHUB_REF pattern, and lines 40–42 write it to .VERSION using overwrite mode. This approach is consistent with the dev workflow and aligns with the PR's versioning centralization, ensuring prod builds use release-tag–derived versions.


47-47: ✓ Docker metadata action upgraded to v5 with explicit semver values.

Line 47 upgrades to docker/metadata-action@v5, resolving the critical actionlint warning. Lines 53–55 use explicit value= parameters to ensure semver tags are derived precisely from the release tag, providing tight control over prod image versioning.

Also applies to: 53-55


60-72: ✓ Improved step clarity with descriptive comments.

Lines 60 and 67 add comments clarifying the purpose of the GHCR and DockerHub login steps. This improves workflow maintainability without changing behavior.

front/plugins/nmap_dev_scan/nmap_dev.py (1)

24-24: LGTM! Removal of timeNowTZ aligns with PR objectives.

The removal of timeNowTZ from the helper imports is correct. This plugin doesn't perform any timestamp operations—it only scans devices and writes results using Plugin_Objects. The change aligns with the broader PR objective to centralize datetime logic and remove legacy time helpers.

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
front/plugins/sync/sync.py (2)

176-206: Verify node name extraction logic for decoded files.

When decode_and_rename_files (imported on line 18) renames encrypted files from .encoded. to .decoded., the filename becomes last_result.decoded.Node_1.1.log. On line 185, file_name.split('.')[1] extracts index 1 which would be 'decoded', not the node name 'Node_1' (which is at index 2).

This logic error would cause incorrect node attribution for encrypted/decoded files, though it works correctly for non-encrypted files like last_result.Node_1.log.

Consider applying this fix to handle both file formats:

-                    # Store e.g. Node_1 from last_result.encoded.Node_1.1.log
-                    syncHubNodeName = file_name.split('.')[1]
+                    # Extract node name from either last_result.decoded.Node_1.1.log or last_result.Node_1.log
+                    parts = file_name.split('.')
+                    # If decoded/encoded file, node name is at index 2; otherwise at index 1
+                    syncHubNodeName = parts[2] if 'decoded' in file_name or 'encoded' in file_name else parts[1]

317-345: Fix return type in error paths to prevent AttributeError.

The get_data function returns an empty string "" on error (lines 337, 345), but the caller on line 137 expects a dictionary and calls .get('node_name', 'unknown_node') on the return value. This would cause an AttributeError since strings don't have a .get() method.

Apply this fix:

                except json.JSONDecodeError:
                    message = f'[{pluginName}] Failed to parse JSON from {final_endpoint}'
                    mylog('verbose', [message])
                    write_notification(message, 'alert', timeNowDB())
-                    return ""
+                    return {}
        except requests.RequestException as e:
            mylog('verbose', [f'[{pluginName}] Error calling {final_endpoint}: {e}'])

    # If all endpoints fail
    message = f'[{pluginName}] Failed to get data from "{node_url}" via all endpoints'
    mylog('verbose', [message])
    write_notification(message, 'alert', timeNowDB())
-    return ""
+    return {}
🧹 Nitpick comments (4)
front/plugins/__test/test.py (1)

23-23: Consider removing unused imports and variables.

While this is a development test file, several imports and variables are unused:

  • getPluginObject (line 23)
  • bytes_to_string, sanitize_string, cleanDeviceName (line 26)
  • plugin_objects (line 37)
  • md5_hash (line 39)

Removing them would reduce noise and make the file's actual dependencies clearer.

Also applies to: 26-26, 37-39

front/plugins/omada_sdn_imp/omada_sdn.py (1)

44-44: Remove unused import.

The get_plugins_configs function is imported but never used in this file.

Apply this diff to remove the unused import:

-from utils.plugin_utils import get_plugins_configs
front/plugins/_publisher_mqtt/mqtt.py (1)

28-28: Remove unused import.

The timeNowDB import is never used in this file. While it was likely added as part of the timestamp utility migration, the prepTimeStamp function at line 571 needs a datetime object rather than a formatted string (which timeNowDB returns), so the direct datetime.now(conf.tz) usage is appropriate for that context.

Apply this diff to remove the unused import:

-from utils.datetime_utils import timeNowDB
docs/API_LOGS.md (1)

19-28: Consider adding a language specifier to the fenced code block.

For consistency and proper syntax highlighting, consider marking the code block as plaintext:

-```
+```plaintext
 app.log
 app_front.log
 IP_changes.log
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68c8e16 and 8483a74.

📒 Files selected for processing (24)
  • docs/API.md (1 hunks)
  • docs/API_GRAPHQL.md (2 hunks)
  • docs/API_LOGS.md (1 hunks)
  • front/php/server/util.php (5 hunks)
  • front/plugins/__template/rename_me.py (1 hunks)
  • front/plugins/__test/test.py (1 hunks)
  • front/plugins/_publisher_mqtt/mqtt.py (2 hunks)
  • front/plugins/dig_scan/digscan.py (1 hunks)
  • front/plugins/freebox/freebox.py (1 hunks)
  • front/plugins/ipneigh/ipneigh.py (1 hunks)
  • front/plugins/nbtscan_scan/nbtscan.py (1 hunks)
  • front/plugins/omada_sdn_imp/omada_sdn.py (1 hunks)
  • front/plugins/sync/sync.py (6 hunks)
  • front/plugins/unifi_api_import/unifi_api_import.py (1 hunks)
  • front/plugins/wake_on_lan/wake_on_lan.py (1 hunks)
  • server/api_server/api_server_start.py (24 hunks)
  • server/api_server/graphql_endpoint.py (3 hunks)
  • server/api_server/logs_endpoint.py (1 hunks)
  • server/initialise.py (3 hunks)
  • server/models/user_events_queue_instance.py (3 hunks)
  • server/plugin.py (10 hunks)
  • server/utils/plugin_utils.py (1 hunks)
  • test/api_endpoints/test_graphq_endpoints.py (1 hunks)
  • test/api_endpoints/test_logs_endpoints.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • front/php/server/util.php
🚧 Files skipped from review as they are similar to previous changes (3)
  • front/plugins/__template/rename_me.py
  • front/plugins/ipneigh/ipneigh.py
  • front/plugins/freebox/freebox.py
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/utils/plugin_utils.py
  • server/api_server/logs_endpoint.py
  • server/models/user_events_queue_instance.py
  • front/plugins/omada_sdn_imp/omada_sdn.py
  • front/plugins/sync/sync.py
  • front/plugins/unifi_api_import/unifi_api_import.py
  • front/plugins/__test/test.py
  • server/api_server/graphql_endpoint.py
  • front/plugins/_publisher_mqtt/mqtt.py
  • test/api_endpoints/test_graphq_endpoints.py
  • front/plugins/dig_scan/digscan.py
  • server/api_server/api_server_start.py
  • test/api_endpoints/test_logs_endpoints.py
  • front/plugins/nbtscan_scan/nbtscan.py
  • front/plugins/wake_on_lan/wake_on_lan.py
  • server/plugin.py
  • server/initialise.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/logs_endpoint.py
  • server/api_server/graphql_endpoint.py
  • server/api_server/api_server_start.py
test/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Tests must reside under 'test/' and use pytest.

Files:

  • test/api_endpoints/test_graphq_endpoints.py
  • test/api_endpoints/test_logs_endpoints.py
server/api_server/api_server_start.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Files:

  • server/api_server/api_server_start.py
server/initialise.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Add or modify settings centrally via 'ccd()' in 'server/initialise.py' or via plugin manifest; never hardcode ports or secrets—always use 'get_setting_value()'.

Files:

  • server/initialise.py
🧠 Learnings (12)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/helper.py : Use 'helper.py' ('timeNowTZ', 'normalize_mac', and sanitizers) for all time, MAC, and string operations; always validate MACs before database writes.

Applied to files:

  • server/utils/plugin_utils.py
📚 Learning: 2025-11-05T04:34:52.339Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • server/utils/plugin_utils.py
  • server/models/user_events_queue_instance.py
  • front/plugins/sync/sync.py
  • front/plugins/__test/test.py
  • front/plugins/_publisher_mqtt/mqtt.py
  • server/api_server/api_server_start.py
📚 Learning: 2025-10-26T19:36:26.482Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1235
File: server/api_server/nettools_endpoint.py:13-34
Timestamp: 2025-10-26T19:36:26.482Z
Learning: In server/api_server/nettools_endpoint.py, the use of print() for module-level initialization warnings is acceptable and should be reviewed by the primary maintainer. The logger.mylog guideline may be specific to plugin code rather than core server code.

Applied to files:

  • server/api_server/logs_endpoint.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/*.py : When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Applied to files:

  • server/api_server/logs_endpoint.py
  • server/api_server/api_server_start.py
📚 Learning: 2025-10-10T22:16:02.770Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1214
File: install/ubuntu24/uninstall.sh:129-141
Timestamp: 2025-10-10T22:16:02.770Z
Learning: NetAlertX uninstall procedures should only remove files from the repository (specifically /app files) and should not touch system packages like PHP, nginx, avahi, or other shared system components to avoid damaging user systems.

Applied to files:

  • server/api_server/logs_endpoint.py
📚 Learning: 2025-09-20T14:08:48.256Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/scripts/setup.sh:90-96
Timestamp: 2025-09-20T14:08:48.256Z
Learning: In the NetAlertX devcontainer setup, the setup.sh script intentionally removes user_notifications.json from the API directory during development environment initialization to prevent notification clutter that accumulates during container launches and development work.

Applied to files:

  • server/api_server/logs_endpoint.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Run plugin scripts as standalone executables with 'sys.path' configured for '/app/front/plugins' and '/app/server', following the provided template.

Applied to files:

  • front/plugins/omada_sdn_imp/omada_sdn.py
  • front/plugins/sync/sync.py
  • front/plugins/unifi_api_import/unifi_api_import.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/*/script.py : Log a concise summary (such as the total number of objects added) at info level before writing the plugin result file; use verbose/debug for extra context.

Applied to files:

  • front/plugins/sync/sync.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to front/plugins/plugin_helper.py : Use 'Plugin_Objects' from 'front/plugins/plugin_helper.py' to sanitize text and normalize MAC addresses before writing results.

Applied to files:

  • front/plugins/unifi_api_import/unifi_api_import.py
  • front/plugins/dig_scan/digscan.py
  • front/plugins/nbtscan_scan/nbtscan.py
  • front/plugins/wake_on_lan/wake_on_lan.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/database.py : Leverage helpers in 'server/database.py' and 'server/db/*' for persistent state with SQLite.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/api_server_start.py : All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-11-02T02:22:10.968Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1261
File: server/app_state.py:106-115
Timestamp: 2025-11-02T02:22:10.968Z
Learning: In server/app_state.py, the pluginsStates parameter always contains complete plugin state objects with the structure: {"PLUGIN_NAME": {"lastChanged": "...", "totalObjects": N, "newObjects": N, "changedObjects": N}}. Type validation before calling .update() is not needed as the maintainer guarantees well-formed objects are always supplied.

Applied to files:

  • server/plugin.py
🧬 Code graph analysis (17)
server/utils/plugin_utils.py (3)
server/helper.py (5)
  • get_file_content (107-113)
  • write_file (116-137)
  • get_setting (149-206)
  • get_setting_value (210-265)
  • setting_value_to_python_type (270-359)
server/app_state.py (1)
  • updateState (156-187)
server/utils/crypto_utils.py (2)
  • decrypt_data (40-46)
  • generate_deterministic_guid (63-66)
server/api_server/logs_endpoint.py (3)
server/logger.py (2)
  • mylog (84-90)
  • Logger (53-94)
server/helper.py (1)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (47-67)
server/models/user_events_queue_instance.py (2)
server/utils/datetime_utils.py (1)
  • timeNowDB (47-67)
server/logger.py (1)
  • mylog (84-90)
front/plugins/omada_sdn_imp/omada_sdn.py (2)
server/utils/plugin_utils.py (1)
  • get_plugins_configs (185-228)
server/helper.py (1)
  • get_setting_value (210-265)
front/plugins/sync/sync.py (4)
server/utils/plugin_utils.py (2)
  • get_plugins_configs (185-228)
  • decode_and_rename_files (280-326)
server/utils/datetime_utils.py (1)
  • timeNowDB (47-67)
server/utils/crypto_utils.py (1)
  • encrypt_data (32-38)
server/messaging/in_app.py (1)
  • write_notification (29-79)
front/plugins/unifi_api_import/unifi_api_import.py (2)
server/utils/plugin_utils.py (1)
  • get_plugins_configs (185-228)
server/helper.py (1)
  • get_setting_value (210-265)
front/plugins/__test/test.py (3)
server/utils/plugin_utils.py (1)
  • getPluginObject (246-276)
front/plugins/plugin_helper.py (1)
  • Plugin_Objects (245-304)
server/helper.py (3)
  • get_setting_value (210-265)
  • bytes_to_string (457-461)
  • sanitize_string (496-500)
server/api_server/graphql_endpoint.py (1)
server/logger.py (1)
  • mylog (84-90)
front/plugins/_publisher_mqtt/mqtt.py (3)
server/utils/plugin_utils.py (1)
  • getPluginObject (246-276)
server/helper.py (2)
  • get_setting_value (210-265)
  • bytes_to_string (457-461)
server/utils/datetime_utils.py (1)
  • timeNowDB (47-67)
test/api_endpoints/test_graphq_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (210-265)
front/plugins/dig_scan/digscan.py (1)
server/utils/plugin_utils.py (1)
  • get_plugins_configs (185-228)
server/api_server/api_server_start.py (3)
server/api_server/logs_endpoint.py (1)
  • clean_log (18-57)
server/models/user_events_queue_instance.py (2)
  • UserEventsQueueInstance (14-121)
  • add_event (86-121)
server/messaging/in_app.py (1)
  • write_notification (29-79)
test/api_endpoints/test_logs_endpoints.py (1)
server/helper.py (1)
  • get_setting_value (210-265)
front/plugins/nbtscan_scan/nbtscan.py (2)
server/utils/plugin_utils.py (1)
  • get_plugins_configs (185-228)
server/helper.py (1)
  • get_setting_value (210-265)
front/plugins/wake_on_lan/wake_on_lan.py (2)
server/utils/plugin_utils.py (1)
  • get_plugins_configs (185-228)
server/helper.py (1)
  • get_setting_value (210-265)
server/plugin.py (6)
server/helper.py (4)
  • get_file_content (107-113)
  • write_file (116-137)
  • get_setting (149-206)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (2)
  • timeNowTZ (32-36)
  • timeNowDB (47-67)
server/app_state.py (1)
  • updateState (156-187)
server/models/notification_instance.py (1)
  • NotificationInstance (28-316)
server/messaging/in_app.py (1)
  • write_notification (29-79)
server/utils/crypto_utils.py (1)
  • generate_deterministic_guid (63-66)
server/initialise.py (6)
server/helper.py (3)
  • getBuildTimeStampAndVersion (639-666)
  • setting_value_to_python_type (270-359)
  • get_setting_value (210-265)
server/utils/datetime_utils.py (1)
  • timeNowDB (47-67)
server/app_state.py (1)
  • updateState (156-187)
server/utils/plugin_utils.py (2)
  • get_plugins_configs (185-228)
  • get_set_value_for_init (331-367)
server/messaging/in_app.py (1)
  • write_notification (29-79)
server/utils/crypto_utils.py (1)
  • get_random_bytes (50-60)
🪛 Gitleaks (8.28.0)
docs/API_GRAPHQL.md

[high] 224-229: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

(curl-auth-header)

🪛 markdownlint-cli2 (0.18.1)
docs/API_LOGS.md

19-19: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff (0.14.3)
server/api_server/logs_endpoint.py

52-52: Do not catch blind exception: Exception

(BLE001)

server/models/user_events_queue_instance.py

115-115: Consider moving this statement to an else block

(TRY300)


117-117: Do not catch blind exception: Exception

(BLE001)

server/api_server/graphql_endpoint.py

286-286: Unused method argument: info

(ARG002)

test/api_endpoints/test_graphq_endpoints.py

28-28: Standard pseudo-random generators are not suitable for cryptographic purposes

(S311)

test/api_endpoints/test_logs_endpoints.py

43-43: Standard pseudo-random generators are not suitable for cryptographic purposes

(S311)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (17)
front/plugins/__test/test.py (1)

23-23: LGTM! Import path updates are correct.

The import path changes correctly reflect the PR's refactoring:

  • getPluginObject moved to utils.plugin_utils namespace
  • timeNowTZ removed as it's unused in this file

These changes are consistent with the PR's centralization of utilities.

Also applies to: 26-26

front/plugins/omada_sdn_imp/omada_sdn.py (1)

47-47: LGTM!

Correctly removed the unused timeNowTZ import while retaining get_setting_value, which is actively used throughout the file (lines 53, 56, 263-267, 429). This aligns with the PR's refactoring objectives.

front/plugins/dig_scan/digscan.py (1)

15-18: LGTM!

Import path updates align with the broader refactoring to centralize utilities under utils.* namespace. Removal of unused timeNowTZ keeps imports clean.

front/plugins/unifi_api_import/unifi_api_import.py (1)

16-19: LGTM!

Import path updates are consistent with the centralized utility refactoring. Removal of unused timeNowTZ is appropriate.

front/plugins/nbtscan_scan/nbtscan.py (1)

15-18: LGTM!

Import changes align with the refactoring to move plugin utilities to utils.plugin_utils. Cleanup of unused timeNowTZ import is good.

front/plugins/wake_on_lan/wake_on_lan.py (1)

16-19: LGTM!

Import path refactoring is consistent with the broader effort to centralize utilities. Removal of the unused timeNowTZ import keeps the code clean.

front/plugins/_publisher_mqtt/mqtt.py (2)

23-23: LGTM! Import path correctly updated.

The import path for getPluginObject has been correctly updated to reflect the new module structure.


571-571: LGTM! Error handling implementation is correct.

The fallback to datetime.now(conf.tz) is appropriate here since prepTimeStamp requires a datetime object to call .isoformat() on line 574, rather than a pre-formatted string.

server/utils/plugin_utils.py (1)

7-9: LGTM! Import path refactoring aligns with centralization.

The import path changes from crypto_utils to utils.crypto_utils and the removal of unused timeNowTZ are consistent with the PR's goal of centralizing timestamp utilities into utils.datetime_utils.

docs/API.md (1)

67-69: LGTM! Documentation accurately reflects new API capabilities.

The expanded GraphQL description and new Logs endpoint entry properly document the new functionality introduced in this PR.

docs/API_GRAPHQL.md (1)

3-262: LGTM! Comprehensive LangStrings documentation.

The documentation clearly explains the new LangStrings query, including parameters, fallback behavior, and practical curl examples. The grammar fix and updated endpoint listing improve clarity.

server/models/user_events_queue_instance.py (1)

86-122: LGTM! Well-structured event queueing method.

The add_event method properly validates inputs, handles errors, and logs appropriately. The use of timeNowDB() aligns with the PR's timestamp utility centralization. The broad exception handling is appropriate for file I/O operations.

test/api_endpoints/test_logs_endpoints.py (1)

1-61: LGTM! Comprehensive test coverage for Logs endpoints.

The tests properly cover success and error scenarios for both log purging and execution queue operations. Token-based authentication is correctly implemented in the test fixtures.

test/api_endpoints/test_graphq_endpoints.py (1)

1-170: LGTM! Thorough GraphQL endpoint test coverage.

The tests comprehensively cover devices, settings, and the new LangStrings queries, including authorization checks, data structure validation, and fallback behavior. The test organization is clear and follows pytest best practices.

server/api_server/logs_endpoint.py (1)

18-51: LGTM! Well-designed log purging function with proper allowlist validation.

The allowlist approach provides good security by restricting which files can be purged. The validation, logging, and notification patterns are consistent with the codebase standards.

front/plugins/sync/sync.py (2)

18-18: LGTM! Import paths updated correctly.

The import paths have been successfully updated to use the new centralized utility modules (utils.plugin_utils, utils.datetime_utils, utils.crypto_utils), aligning with the PR's refactoring objectives. All imported functions are used correctly throughout the file.

Also applies to: 21-23


153-153: LGTM! Timestamp utility updated correctly.

The change from timeNowTZ() to timeNowDB() correctly uses the new centralized datetime utility. The timestamps are properly passed to write_notification() for all notification calls.

Also applies to: 259-259, 303-303, 312-312, 336-336, 344-344

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8483a74 and 6d70a8a.

📒 Files selected for processing (4)
  • .github/ISSUE_TEMPLATE/i-have-an-issue.yml (3 hunks)
  • front/plugins/sync/sync.py (7 hunks)
  • server/api_server/api_server_start.py (24 hunks)
  • server/api_server/logs_endpoint.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • front/plugins/sync/sync.py
🧰 Additional context used
📓 Path-based instructions (3)
server/api_server/api_server_start.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Files:

  • server/api_server/api_server_start.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/api_server_start.py
  • server/api_server/logs_endpoint.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/api_server/api_server_start.py
  • server/api_server/logs_endpoint.py
🧠 Learnings (7)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/*.py : When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Applied to files:

  • server/api_server/api_server_start.py
  • server/api_server/logs_endpoint.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/api_server_start.py : All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-11-05T04:34:52.339Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/database.py : Leverage helpers in 'server/database.py' and 'server/db/*' for persistent state with SQLite.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-10T22:16:02.770Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1214
File: install/ubuntu24/uninstall.sh:129-141
Timestamp: 2025-10-10T22:16:02.770Z
Learning: NetAlertX uninstall procedures should only remove files from the repository (specifically /app files) and should not touch system packages like PHP, nginx, avahi, or other shared system components to avoid damaging user systems.

Applied to files:

  • server/api_server/logs_endpoint.py
📚 Learning: 2025-09-20T14:08:48.256Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/scripts/setup.sh:90-96
Timestamp: 2025-09-20T14:08:48.256Z
Learning: In the NetAlertX devcontainer setup, the setup.sh script intentionally removes user_notifications.json from the API directory during development environment initialization to prevent notification clutter that accumulates during container launches and development work.

Applied to files:

  • server/api_server/logs_endpoint.py
📚 Learning: 2025-09-20T14:09:29.159Z
Learnt from: adamoutler
Repo: jokob-sk/NetAlertX PR: 1184
File: .devcontainer/scripts/setup.sh:103-116
Timestamp: 2025-09-20T14:09:29.159Z
Learning: In NetAlertX devcontainer setup, the netalertx user has write permissions to /var/log/nginx/ directory as it's explicitly chowned to netalertx:www-data in the Dockerfile, so setup.sh can write to nginx log files without sudo.

Applied to files:

  • .github/ISSUE_TEMPLATE/i-have-an-issue.yml
🧬 Code graph analysis (2)
server/api_server/api_server_start.py (4)
server/helper.py (1)
  • get_setting_value (210-265)
server/api_server/logs_endpoint.py (1)
  • clean_log (18-57)
server/models/user_events_queue_instance.py (2)
  • UserEventsQueueInstance (14-121)
  • add_event (86-121)
server/messaging/in_app.py (1)
  • write_notification (29-79)
server/api_server/logs_endpoint.py (2)
server/logger.py (2)
  • mylog (84-90)
  • Logger (53-94)
server/helper.py (1)
  • get_setting_value (210-265)
🪛 Ruff (0.14.3)
server/api_server/logs_endpoint.py

52-52: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (4)
.github/ISSUE_TEMPLATE/i-have-an-issue.yml (1)

49-49: LGTM! Enhanced issue template guidance.

The updates improve the issue reporting process by:

  • Clarifying what relevant app.conf settings to include
  • Expanding debug/trace logging requirements with clear confirmation
  • Adding email option for log submission
  • Making Docker logs mandatory with detailed retrieval instructions

These changes will help users provide better diagnostic information.

Also applies to: 73-79, 88-88, 91-97

server/api_server/logs_endpoint.py (1)

1-57: LGTM! Logs endpoint properly implemented.

The clean_log function correctly:

  • Validates log files against an allowed list
  • Uses proper error handling with appropriate status codes
  • Logs and notifies on all code paths
  • Returns consistent JSON responses

The past review concerns about error handling (empty log message, missing notification parameter, wrong status code) have all been addressed.

server/api_server/api_server_start.py (2)

52-62: LGTM! Consistent 404 error handler.

The custom 404 handler provides a standardized JSON response that aligns with the unified error handling pattern used throughout the API.


380-414: LGTM! Logs endpoints properly secured and implemented.

Both new endpoints (api_clean_log and api_add_to_execution_queue) correctly:

  • Enforce authorization checks as required by coding guidelines
  • Validate required parameters
  • Return consistent JSON responses
  • Handle errors appropriately

The past review concern about missing authorization on api_add_to_execution_queue has been addressed.

As per coding guidelines

adamoutler and others added 2 commits November 9, 2025 16:56
Removed unnecessary blank lines in the nginx configuration template.
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
server/api_server/api_server_start.py (1)

391-414: Refine the error field for consistency.

The endpoint correctly enforces authorization and validates input. However, line 412 sets the error field to the generic string "ERROR", while other endpoints in this file provide specific error descriptions (e.g., line 155: "macFrom and macTo are required", line 405: "Missing required 'action' field in JSON body"). Since the message field already contains the descriptive error from queue.add_event, consider using a more specific error label or using the message content.

Apply this diff to improve consistency:

     success, message = queue.add_event(action)
     status_code = 200 if success else 400

     response = {"success": success, "message": message}
     if not success:
-        response["error"] = "ERROR"
+        response["error"] = "Failed to queue event"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d70a8a and 9f6086e.

📒 Files selected for processing (1)
  • server/api_server/api_server_start.py (24 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
server/api_server/api_server_start.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Files:

  • server/api_server/api_server_start.py
server/api_server/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Files:

  • server/api_server/api_server_start.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use 'logger.mylog' for logging at levels: none, minimal, verbose, debug, or trace.

Files:

  • server/api_server/api_server_start.py
🧠 Learnings (4)
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/*.py : When introducing new server functionality, add endpoints only within 'server/api_server/*' and keep authorization checks consistent.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/api_server/api_server_start.py : All API endpoints must enforce Authorization headers: 'Authorization: Bearer <API_TOKEN>' obtained via 'get_setting_value('API_TOKEN')'.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-11-05T04:34:52.339Z
Learnt from: jokob-sk
Repo: jokob-sk/NetAlertX PR: 1271
File: server/helper.py:50-71
Timestamp: 2025-11-05T04:34:52.339Z
Learning: In the NetAlertX codebase, `timeNowDB` function is intentionally duplicated in both `server/helper.py` and `server/logger.py` to prevent circular import issues, since `helper.py` imports from `logger.py` (`from logger import mylog, logResult`). This duplication is by design.

Applied to files:

  • server/api_server/api_server_start.py
📚 Learning: 2025-10-21T01:40:24.597Z
Learnt from: CR
Repo: jokob-sk/NetAlertX PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-10-21T01:40:24.597Z
Learning: Applies to server/database.py : Leverage helpers in 'server/database.py' and 'server/db/*' for persistent state with SQLite.

Applied to files:

  • server/api_server/api_server_start.py
🧬 Code graph analysis (1)
server/api_server/api_server_start.py (2)
server/api_server/logs_endpoint.py (1)
  • clean_log (18-57)
server/models/user_events_queue_instance.py (2)
  • UserEventsQueueInstance (14-121)
  • add_event (86-121)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: docker_dev
🔇 Additional comments (4)
server/api_server/api_server_start.py (4)

55-62: LGTM - Clean 404 handler implementation.

The custom error handler provides a consistent JSON response structure that aligns with other API responses in this file.


27-28: LGTM - Necessary imports for new logs functionality.

These imports support the new /logs endpoints added below.


46-46: LGTM - CORS configuration updated appropriately.

The addition of /logs/* to CORS resources is consistent with other endpoint patterns.


380-389: LGTM - Proper authorization and validation.

The endpoint correctly enforces authorization, validates the required file parameter, and delegates to the clean_log helper which performs whitelist validation.

As per coding guidelines

jokob-sk and others added 7 commits November 10, 2025 10:11
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
@jokob-sk jokob-sk merged commit ac957ce into main Nov 10, 2025
4 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 22, 2025
@coderabbitai coderabbitai bot mentioned this pull request Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants