Skip to content

Next release#1634

Open
jokob-sk wants to merge 26 commits into
mainfrom
next_release
Open

Next release#1634
jokob-sk wants to merge 26 commits into
mainfrom
next_release

Conversation

@jokob-sk
Copy link
Copy Markdown
Collaborator

@jokob-sk jokob-sk commented May 9, 2026

Summary by CodeRabbit

  • Improvements

    • App-upgrade notification visuals now use icons and a clearer release-notes label.
    • Workflows handle missing objects more robustly and simplify action execution.
    • Device page title/navigation improved with smarter cache fallback and navigation hiding when device missing.
    • ICMP scanning: per-interface probing, IPv4/IPv6 handling, deduplication and tolerant timeouts.
    • Sync/DIGSCAN timing and defaults adjusted; sync emits verbose-only messages when applicable.
    • Timezone handling and date parsing tightened; table/modal selectors more robust.
  • Documentation

    • Updated repo badge and added an “Other Alternative Apps” entry.

Review Change Stack

jokob-sk and others added 2 commits May 10, 2026 08:45
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 9, 2026

Important

Review skipped

This PR was authored by the user configured for CodeRabbit reviews. CodeRabbit does not review PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6425bfa-5f07-4ddc-a928-261ede42e3d3

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes safe trigger/object handling and makes Action.execute() parameterless; updates action subclasses and orchestration; refactors device page title resolution to async with cache retry and REST fallback; adjusts DIGSCAN scheduling and plugin default; replaces upgrade emojis with Font Awesome icons; logging, ICMP scan, timezone, and README/config tweaks.

Changes

Workflow Action Execution Refactoring

Layer / File(s) Summary
Trigger Null Safety
server/workflows/triggers.py
Trigger.__init__ sets self.object = None when DB lookup returns no rows.
Action Interface and Helper
server/workflows/actions.py
Added Action.get_object() to normalize trigger.object; changed abstract Action.execute(self, obj)Action.execute(self).
Action Subclass Updates
server/workflows/actions.py
UpdateFieldAction, DeleteObjectAction, RunPluginAction, SendNotificationAction call get_object(), early-return when missing, route by objectGuid/devGUID, and log unsupported formats.
ActionGroup Orchestration
server/workflows/actions.py
ActionGroup.execute() now calls action.execute() without parameters and stops passing/returning the object.

Notification UI Icon Update

Layer / File(s) Summary
Upgrade Notification Markup
server/initialise.py
App-upgrade notification HTML now uses inline Font Awesome <i> icons for the rocket indicator and the release notes link label.

Device Page Title & Navigation

Layer / File(s) Summary
Navigation Visibility
front/deviceDetails.php
updateChevrons() hides #txtRecord, #btnPrevious, and #btnNext when device remains missing after re-cache and logs a warning.
DOM Helper for Page Title
front/deviceDetails.php
Added applyDevicePageTitle(mac, name, owner) to centralize DOM updates for #pageTitle and #devicePageInfoPlc.
Async Device Name Resolution
front/deviceDetails.php
updateDevicePageName(mac) rewritten as async: cache lookup → optional forced re-cache → REST fallback via getAuthContext()+fetch → apply via applyDevicePageTitle().

README Badge Update

Layer / File(s) Summary
Badge Link/Image
README.md
Trendshift badge repository id updated from 12670 to 19712; "Domotz" added to alternatives list.

DIGSCAN Configuration

Layer / File(s) Summary
Backend DIGSCAN schedule
back/app.conf
Added DIGSCAN_RUN='before_name_updates' to scanner run schedule.
Plugin RUN default
front/plugins/dig_scan/config.json
Changed RUN default from before_name_updates to disabled.

ICMP Scan Update

Layer / File(s) Summary
Per-interface fping and dedupe
front/plugins/icmp_scan/icmp.py
run_fping expands CIDRs, handles empty target lists, splits IPv4/IPv6, runs fping per interface/family, continues on process errors/timeouts, parses/filters output case-insensitively, and deduplicates alive IPs across interfaces.

Sync Endpoint Logging

Layer / File(s) Summary
Logger init and conditional notification
server/api_server/sync_endpoint.py
Module-level lggr = Logger(get_setting_value('LOG_LEVEL')); handle_sync_get logs verbose and only writes the in-app notification when lggr.isAbove('verbose').

Session Timestamps

Layer / File(s) Summary
DataTable timestamp localization
front/deviceDetailsSessions.php
Stop stripping timezone offsets; pass full timestamp cellData to localizeTimestamp.

Sync Plugin Config

Layer / File(s) Summary
SET_ALWAYS options & Dummy mapping
front/plugins/sync/config.json
Added devLastIP to SET_ALWAYS options; changed Dummy mapped_to_column_data.value from "sync" to "SYNC".

API Server Start Formatting

Layer / File(s) Summary
Separator adjustment
server/api_server/api_server_start.py
Removed/adjusted line(s) between is_authorized() and /mcp/sse route decorator; no handler change.

Messaging / Reporting Timezone

Layer / File(s) Summary
Timezone conversion usage
server/messaging/reporting.py
get_notifications() applies apply_timezone_to_json(json_obj, section) and uses converted data for per-section payloads; minor comment/spacing changes elsewhere.

Datetime Utils

Layer / File(s) Summary
format_date_iso UTC-first conversion
server/utils/datetime_utils.py
Normalize parsed datetimes to UTC before converting to configured timezone; resolve conf.tz via ZoneInfo(str(conf.tz)) when appropriate and broaden exception handling.

Sequence Diagram(s)

sequenceDiagram
  participant Trigger
  participant ActionGroup
  participant UpdateFieldAction
  participant DeleteObjectAction
  participant RunPluginAction
  participant SendNotificationAction
  participant DB

  Trigger->>ActionGroup: trigger fires
  ActionGroup->>UpdateFieldAction: action.execute()
  UpdateFieldAction->>DB: Action.get_object() -> dict or None
  alt object present
    UpdateFieldAction->>DB: update by objectGuid/devGUID
    DeleteObjectAction->>DB: delete by objectGuid/devGUID
    RunPluginAction->>RunPluginAction: execute plugin with object
    SendNotificationAction->>SendNotificationAction: log/emit notification (when supported)
  else missing
    UpdateFieldAction-->>ActionGroup: early return / log
  end
  ActionGroup-->>Trigger: complete
Loading

Possibly related PRs

"🐰 I hopped through code where actions sleep,
Turned rows to dicts, made execute run neat,
Page titles fetch with cache then fetch anew,
Rockets now fa-solid, badges changed their view,
A tidy hop — small fixes, springtime beat."

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Next release' is vague and generic, providing no meaningful information about what changes are actually included in this pull request. Replace with a descriptive title summarizing the main changes, such as 'Add workflow object normalization and device details enhancements' or similar that reflects the primary technical improvements.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/workflows/actions.py`:
- Around line 105-107: When the code logs "[WF] Unsupported object format:
{obj}" it should follow the same early-return pattern used in UpdateFieldAction
and return None instead of returning the original obj; update the
function/method that contains the mylog call (the block that currently does
mylog("none", f"[WF] Unsupported object format: {obj}") followed by return obj)
to return None so callers get a clear failure signal for unsupported formats.
- Around line 70-72: The function logs unsupported object formats with mylog but
then returns the original obj, which is inconsistent with the earlier
None-return pattern; modify the branch that detects missing objectGuid and
devGUID (the unsupported-format case) to return None instead of obj so callers
receive a clear failure signal; update any docstring/comments for the enclosing
function (in server/workflows/actions.py) if present to reflect that unsupported
formats return None and run tests that call this function to ensure callers
handle None appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e7d1402-381e-4f54-a7d8-294fa1901f80

📥 Commits

Reviewing files that changed from the base of the PR and between 190262a and 300820e.

📒 Files selected for processing (3)
  • server/initialise.py
  • server/workflows/actions.py
  • server/workflows/triggers.py

Comment thread server/workflows/actions.py Outdated
Comment thread server/workflows/actions.py Outdated
jokob-sk added 2 commits May 9, 2026 23:35
- Updated Trendshift repository link in README.md.
- Improved error handling and user feedback in deviceDetails.php:
  - Added warnings for device not found scenarios.
  - Refactored device name and owner retrieval logic with caching and REST API fallback.
coderabbitai[bot]

This comment was marked as off-topic.

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/dig_scan/config.json`:
- Line 55: The upgrade will cause existing installs without an explicit
DIGSCAN_RUN in their app.conf to inherit the new config.json default
("disabled") because initialiseFile() only creates a template when the file is
missing; to fix, add a migration or merge step that runs at startup (or enhance
initialiseFile()) to read the existing app.conf and, if DIGSCAN_RUN is absent,
set and persist DIGSCAN_RUN='before_name_updates' (the new intended default from
back/app.conf) so upgrades keep the new behavior, or alternatively surface a
clear upgrade notice to users to set DIGSCAN_RUN explicitly; reference the
symbols: DIGSCAN_RUN, initialiseFile(), config.json (default_value), and
back/app.conf (intended default).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c6185fd5-c24a-46d8-a963-5b319dc79d4f

📥 Commits

Reviewing files that changed from the base of the PR and between f428f45 and f11a63b.

📒 Files selected for processing (3)
  • back/app.conf
  • front/plugins/dig_scan/config.json
  • server/initialise.py

]
},
"default_value": "before_name_updates",
"default_value": "disabled",
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 12, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how plugin defaults are initialized and if there's migration for this change

# Look for default value handling in the plugin initialization
rg -nP -C5 'default_value.*before_name_updates|DIGSCAN_RUN' --type=py

# Check for any upgrade migration logic that might handle this change
ast-grep --pattern 'def $FUNC($$$) {
  $$$
  DIGSCAN
  $$$
}'

# Look for how settings from app.conf override plugin defaults
rg -nP -C3 'def (importConfigs|ccd|get_set_value)' server/initialise.py

Repository: netalertx/NetAlertX

Length of output: 1188


🏁 Script executed:

# Examine the config.json file to verify the default_value at line 55
cat -n front/plugins/dig_scan/config.json | head -70

Repository: netalertx/NetAlertX

Length of output: 2157


🏁 Script executed:

# Check back/app.conf for DIGSCAN_RUN setting at line 33
cat -n back/app.conf | sed -n '25,45p'

Repository: netalertx/NetAlertX

Length of output: 969


🏁 Script executed:

# Find where DIGSCAN_RUN or the RUN setting is referenced to understand default handling
rg -n "RUN.*default" front/plugins/dig_scan/config.json -A 2 -B 2

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Understand how defaults are applied - examine the ccd() function and surrounding code
sed -n '58,120p' server/initialise.py

Repository: netalertx/NetAlertX

Length of output: 1761


🏁 Script executed:

# Check for upgrade/migration related code
rg -n "migrate|upgrade|DIGSCAN" server/initialise.py | head -20

Repository: netalertx/NetAlertX

Length of output: 335


🏁 Script executed:

# Find where ccd() is called for DIGSCAN_RUN specifically
rg -n "DIGSCAN_RUN|ccd\(" server/initialise.py -B 2 -A 2 | head -50

Repository: netalertx/NetAlertX

Length of output: 1382


🏁 Script executed:

# Understand how app.conf is loaded - search for where configuration files are parsed
rg -n "app\.conf|load.*config|parse.*config" server/initialise.py | head -20

Repository: netalertx/NetAlertX

Length of output: 141


🏁 Script executed:

# Look at the importConfigs function more completely to understand the flow
sed -n '195,300p' server/initialise.py

Repository: netalertx/NetAlertX

Length of output: 4995


🏁 Script executed:

# Search for where plugin settings from config.json are initialized with defaults
rg -n "default_value" server/initialise.py -B 3 -A 3

Repository: netalertx/NetAlertX

Length of output: 414


🏁 Script executed:

# Check if there's any special handling when loading app.conf for upgrades
rg -n "app\.conf" . --type=py | grep -i "upgrade\|migrate\|load"

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Find the read_config_file implementation
rg -n "def read_config_file" server/initialise.py -A 20

Repository: netalertx/NetAlertX

Length of output: 1069


🏁 Script executed:

# Check how environment variables and app.conf are merged/loaded
rg -n "fullConfPath\|read_config_file" server/initialise.py -B 2 -A 2

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Look for any automatic migration that adds settings to app.conf on upgrade
rg -n "write.*app\.conf\|update.*config\|DIGSCAN_RUN" server/initialise.py

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Check git history to see when the default changed
git log --oneline -- front/plugins/dig_scan/config.json back/app.conf | head -20

Repository: netalertx/NetAlertX

Length of output: 150


🏁 Script executed:

# Search across the codebase for how DIGSCAN_RUN was used before
git log -p --all -S "DIGSCAN_RUN" -- front/plugins/dig_scan/config.json | head -100

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Get the full commit details for the DIGSCAN fix
git log --all -p -S "DIGSCAN could not" | head -200

Repository: netalertx/NetAlertX

Length of output: 149


🏁 Script executed:

# Show what was changed in config.json related to DIGSCAN defaults
git show f11a63bb -- front/plugins/dig_scan/config.json | head -100

Repository: netalertx/NetAlertX

Length of output: 2860


🏁 Script executed:

# Check if there's any other reference to issue `#1631`
rg -n "1631\|DIGSCAN.*disabled" . --type=py --type=md --type=json | head -20

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Look at the broader context - what was the default before?
git log --all --oneline -p -- front/plugins/dig_scan/config.json | grep -A 5 -B 5 "default_value" | head -50

Repository: netalertx/NetAlertX

Length of output: 1355


🏁 Script executed:

# Check if there are any references to dig_scan config.json before the recent commit
git log --all --oneline -- front/plugins/dig_scan/config.json | head -10

Repository: netalertx/NetAlertX

Length of output: 509


🏁 Script executed:

# Look for migration or initialization logic that might add DIGSCAN_RUN to app.conf
rg -n "renameSettings\|migrate\|add.*to.*conf\|write.*app\.conf" server/initialise.py -A 5 | head -60

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Check the renameColumnReferences function to understand migration patterns
sed -n '913,950p' server/initialise.py

Repository: netalertx/NetAlertX

Length of output: 1247


🏁 Script executed:

# Look for any logic that updates or adds missing settings to app.conf during upgrade
rg -n "def.*upgrade|upgrade.*config|config.*upgrade" server/ --type=py | head -20

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Check if there's template or initialization for app.conf that would include DIGSCAN_RUN
rg -n "app\.conf" . --type=py | grep -E "template|default|init" | head -15

Repository: netalertx/NetAlertX

Length of output: 256


🏁 Script executed:

# Check git history for when DIGSCAN_RUN was added to app.conf
git log --all --oneline -p -- back/app.conf | grep -B 5 -A 5 "DIGSCAN_RUN" | head -40

Repository: netalertx/NetAlertX

Length of output: 419


🏁 Script executed:

# Examine the initialiseFile function to understand how app.conf is set up
rg -n "def initialiseFile" server/helper.py -A 30

Repository: netalertx/NetAlertX

Length of output: 1739


🏁 Script executed:

# Check if app.conf gets updated/merged with defaults during startup
rg -n "app\.conf.*write\|append.*app\.conf\|update.*app\.conf" server/ --type=py -B 2 -A 2

Repository: netalertx/NetAlertX

Length of output: 45


🏁 Script executed:

# Look at what the default app.conf template contains and when it's used
cat -n back/app.conf | head -50

Repository: netalertx/NetAlertX

Length of output: 2314


🏁 Script executed:

# Check if there's any logic that compares app.conf with defaults and fills in missing settings
rg -n "missing.*setting|new.*setting|upgrade.*setting" server/initialise.py -B 2 -A 5

Repository: netalertx/NetAlertX

Length of output: 397


Confirm the upgrade path for existing installations without explicit DIGSCAN_RUN configuration.

The change is correct in principle: new installations get DIGSCAN_RUN='before_name_updates' from back/app.conf line 33, and the config.json default is now disabled. However, existing installations that upgrade will be affected: if they don't already have DIGSCAN_RUN explicitly set in their app.conf, they will inherit the new disabled default from config.json since initialiseFile() only copies the template app.conf when the file is missing—it does not merge new settings into existing installations. Users should be notified of this change or a migration mechanism should be added to automatically set DIGSCAN_RUN='before_name_updates' for existing users on upgrade.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/plugins/dig_scan/config.json` at line 55, The upgrade will cause
existing installs without an explicit DIGSCAN_RUN in their app.conf to inherit
the new config.json default ("disabled") because initialiseFile() only creates a
template when the file is missing; to fix, add a migration or merge step that
runs at startup (or enhance initialiseFile()) to read the existing app.conf and,
if DIGSCAN_RUN is absent, set and persist DIGSCAN_RUN='before_name_updates' (the
new intended default from back/app.conf) so upgrades keep the new behavior, or
alternatively surface a clear upgrade notice to users to set DIGSCAN_RUN
explicitly; reference the symbols: DIGSCAN_RUN, initialiseFile(), config.json
(default_value), and back/app.conf (intended default).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@coderabbitai double check - existing installations with DIGSCAN enabled will have their own the DIGSCAN_RUN setting already specidfied in teh app.conf so this should be a non-issue - but challenge me if wrong

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if DIGSCAN_RUN existed in app.conf before this PR (history)
git log --all --oneline -- back/app.conf | head -20

echo "---DIGSCAN_RUN in git history---"
git log --all -p -- back/app.conf | grep -B 5 -A 5 "DIGSCAN_RUN" | head -60

echo "---Current app.conf DIGSCAN lines---"
grep -n "DIGSCAN" back/app.conf

echo "---Check how plugin settings are written to app.conf---"
rg -n "def.*write.*conf\|def.*save.*conf\|def.*persist\|def.*update.*conf" server/ --type=py | head -20

echo "---Check if ccd() or plugin init writes settings to app.conf---"
rg -n "app\.conf.*write\|write.*app\.conf\|open.*app\.conf.*w" server/ --type=py -B 2 -A 5 | head -60

echo "---Check how settings from plugin config.json get persisted---"
rg -n "def ccd\|def saveConfParameter\|def writeSettingsToFile" server/initialise.py -A 20 | head -80

echo "---Look for savePlugin or importPlugin in the codebase---"
rg -n "def.*save.*plugin\|def.*import.*plugin\|writePlugin" server/ --type=py | head -20

Length of output: 1694


@jokob-sk, I dug into the git history of back/app.conf and the key finding is:

DIGSCAN_RUN was NOT present in back/app.conf in any prior commit — it is introduced for the first time in this very PR.

So your claim holds for users who explicitly configured and saved DIGSCAN settings through the UI (those writes would land in their app.conf). However, the edge case that remains is:

Users who had DIGSCAN running with the old before_name_updates default but never explicitly saved that setting through the UI — their app.conf would have no DIGSCAN_RUN entry. After the upgrade, initialiseFile() won't merge the new back/app.conf template entry into their existing file, so they'd fall back to the new config.json default of disabled.

Since DIGSCAN is in the default LOADED_PLUGINS, this could affect a non-trivial number of passive users.

That said, this PR is explicitly fixing #1631 ("DIGSCAN could not be disabled"), and the intent of the change is clear. If the release notes or upgrade notice calls this out, it's a reasonable trade-off. If you'd prefer to be safe, the only mitigation would be a startup merge step that writes DIGSCAN_RUN='before_name_updates' into existing app.conf files that lack the key — but that's a non-trivial change.


🧠 Learnings used
Learnt from: jokob-sk
Repo: netalertx/NetAlertX PR: 1435
File: front/plugins/dig_scan/config.json:85-87
Timestamp: 2026-01-20T23:55:35.174Z
Learning: JSON parsers ignore whitespace between tokens. A leading whitespace after the opening brace is valid and should not trigger a missing comma error. This applies to plugin config files like front/plugins/**/config.json and similar config.json files in plugin directories; only flag real syntax errors or missing commas when the JSON structure itself is invalid.

Learnt from: jokob-sk
Repo: netalertx/NetAlertX PR: 1636
File: front/plugins/kea_api/config.json:332-332
Timestamp: 2026-05-10T21:47:05.302Z
Learning: When reviewing NetAlertX plugin configuration files (config.json) under front/plugins, use the exact elementOptions ordering property key "orderable". Do not flag "orderable" as a misspelling and do not suggest changing it to "ordeable"; this spelling is intentionally used consistently across plugin config.json files (including templates and concrete plugins).

Copy link
Copy Markdown
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.

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

11-12: ⚡ Quick win

Avoid caching LOG_LEVEL at module import time.

Line 12 initializes lggr once, so Line 35 can use stale verbosity after runtime setting changes. Build the logger (or read level) at call time for this check.

♻️ Proposed fix
-# Make sure log level is initialized correctly
-lggr = Logger(get_setting_value('LOG_LEVEL'))
-
 def handle_sync_get():
@@
-    if lggr.isAbove('verbose'):
+    if Logger(get_setting_value("LOG_LEVEL")).isAbove("verbose"):
         write_notification(message, 'info', timeNowUTC())

Also applies to: 35-36

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/api_server/sync_endpoint.py` around lines 11 - 12, The module
currently creates lggr = Logger(get_setting_value('LOG_LEVEL')) at import time
which freezes the log level; remove that module-level initialization and instead
build or read the level at call time—add a small accessor like get_logger() that
returns Logger(get_setting_value('LOG_LEVEL')) (or call
Logger(get_setting_value('LOG_LEVEL')) inline) and replace all uses of the
imported lggr (including the runtime verbosity check that currently reads lggr
around where you referenced lines 35-36) to call get_logger() or read
get_setting_value('LOG_LEVEL') directly so the logger respects runtime changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/api_server/sync_endpoint.py`:
- Around line 11-12: The module currently creates lggr =
Logger(get_setting_value('LOG_LEVEL')) at import time which freezes the log
level; remove that module-level initialization and instead build or read the
level at call time—add a small accessor like get_logger() that returns
Logger(get_setting_value('LOG_LEVEL')) (or call
Logger(get_setting_value('LOG_LEVEL')) inline) and replace all uses of the
imported lggr (including the runtime verbosity check that currently reads lggr
around where you referenced lines 35-36) to call get_logger() or read
get_setting_value('LOG_LEVEL') directly so the logger respects runtime changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a5675cbf-1953-45a3-a883-976b65b7b407

📥 Commits

Reviewing files that changed from the base of the PR and between f11a63b and 0127194.

📒 Files selected for processing (1)
  • server/api_server/sync_endpoint.py

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/icmp_scan/icmp.py`:
- Around line 216-236: The current loop uses a single is_ipv6 flag for the whole
batch, causing the "-6" option to be applied to IPv4 targets; change the logic
in the block that builds fping commands (the code around is_ipv6,
interface_list, for interface in interface_list, and cmd construction) to split
targets into two lists (ipv4_targets and ipv6_targets based on presence of ':'),
then iterate families: for each non-empty family list build cmd per interface
and only append "-6" when handling the ipv6_targets family; ensure you replace
uses of the single is_ipv6 variable with a per-invocation family check so IPv4
runs never include "-6" and IPv6 runs always include "-6".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff468d7e-8488-47f5-9b15-9c7615ee3e7e

📥 Commits

Reviewing files that changed from the base of the PR and between f11a63b and 09744f3.

📒 Files selected for processing (2)
  • front/plugins/icmp_scan/icmp.py
  • server/api_server/sync_endpoint.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/api_server/sync_endpoint.py

Comment thread front/plugins/icmp_scan/icmp.py Outdated
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/icmp_scan/icmp.py`:
- Around line 223-229: The loop iterates over interface_list built from
interfaces and will re-scan duplicate interface entries; deduplicate interfaces
before creating interface_list to avoid repeated scans (and preserve order).
Replace the current interface_list assignment logic (where interface_list =
interfaces if interfaces else [None]) with a deduplication step that builds a
list of unique interfaces (preserving first-seen order) and falls back to [None]
when interfaces is falsy, then iterate for interface in interface_list as
before.
- Around line 211-214: The code currently calls expand_subnets(targets)
unconditionally which can expand huge CIDRs into massive in-memory lists; before
expanding, compute an estimated host count for the provided CIDRs (using the
ipaddress module or a helper like count_hosts_in_subnets(targets)) and guard it
against a sensible MAX_TARGETS threshold (e.g., 65k) — if the estimate exceeds
the threshold, log/return an error or slice/refuse the request; alternatively
modify expand_subnets to accept a max_hosts parameter or return a
generator/streamed iterator to avoid allocating all hosts at once; update the
call site around expand_subnets and the subsequent handling of targets (the
targets variable and any fping invocation) to respect this guard.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 64ec046a-433e-485a-9f55-abe14cfa5a93

📥 Commits

Reviewing files that changed from the base of the PR and between f11a63b and 92adadd.

📒 Files selected for processing (2)
  • front/plugins/icmp_scan/icmp.py
  • server/api_server/sync_endpoint.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/api_server/sync_endpoint.py

Comment thread front/plugins/icmp_scan/icmp.py
Comment thread front/plugins/icmp_scan/icmp.py
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/messaging/reporting.py`:
- Around line 229-234: The current except block around
apply_timezone_to_json(json_obj, section) drops the whole section on failure;
instead, catch the exception, log it (using mylog) and set data to the original
raw DB payload (json_obj or the variable that holds raw rows) so the section is
preserved, then continue to assign final_json[section] = data; update the except
block that references apply_timezone_to_json, mylog, json_obj, section and
final_json accordingly (remove the continue and fallback to raw data).

In `@server/utils/datetime_utils.py`:
- Around line 215-218: The current broad except Exception around constructing
target_tz can mask unrelated errors; narrow it to catch only
ZoneInfoNotFoundError and ValueError when calling ZoneInfo(str(conf.tz)) so that
conf.tz handling (involving conf.tz, ZoneInfo, ZoneInfoNotFoundError,
ValueError) falls back to datetime.UTC for unknown/invalid tz values while
allowing other exceptions to surface; update the except clause accordingly and
keep assignment to target_tz and the UTC fallback intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 15bfbc22-9b65-4a92-92b8-5e53053fb3cd

📥 Commits

Reviewing files that changed from the base of the PR and between 92adadd and 47a5591.

📒 Files selected for processing (5)
  • front/deviceDetailsSessions.php
  • front/plugins/sync/config.json
  • server/api_server/api_server_start.py
  • server/messaging/reporting.py
  • server/utils/datetime_utils.py
💤 Files with no reviewable changes (2)
  • front/deviceDetailsSessions.php
  • server/api_server/api_server_start.py

Comment thread server/messaging/reporting.py
Comment on lines +215 to +218
try:
target_tz = conf.tz if isinstance(conf.tz, datetime.tzinfo) else ZoneInfo(str(conf.tz))
except Exception:
target_tz = datetime.UTC
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify broad exception handling and related BLE001 occurrences.
rg -n -C2 'except Exception' server/utils/datetime_utils.py
rg -n -C2 'format_date_iso\(' server/utils/datetime_utils.py

Repository: netalertx/NetAlertX

Length of output: 1209


🏁 Script executed:

head -50 server/utils/datetime_utils.py

Repository: netalertx/NetAlertX

Length of output: 1812


🏁 Script executed:

sed -n '200,230p' server/utils/datetime_utils.py

Repository: netalertx/NetAlertX

Length of output: 1157


🏁 Script executed:

rg -n 'import.*ZoneInfo' server/utils/datetime_utils.py

Repository: netalertx/NetAlertX

Length of output: 118


🏁 Script executed:

rg -n 'from.*ZoneInfo' server/utils/datetime_utils.py

Repository: netalertx/NetAlertX

Length of output: 118


🌐 Web query:

ZoneInfo constructor exceptions raised Python zoneinfo

💡 Result:

The Python zoneinfo.ZoneInfo constructor raises specific exceptions depending on the nature of the failure during object instantiation [1][2]. Primary Exceptions: - ZoneInfoNotFoundError: This exception is raised when the specified time zone key cannot be found on the system or within the available tzdata package [1][2]. It is a subclass of KeyError [1][2]. - ValueError: This exception is raised if the provided key is not a valid, normalized relative POSIX path (e.g., it contains up-level references like '..' or is otherwise non-conforming) [1][2]. Additionally, if using the ZoneInfo.from_file constructor, ValueError is raised if the data read from the file is not a valid TZif file [1][2]. Related Warnings and Other Errors: - InvalidTZPathWarning: This is a warning (not an exception) raised when the PYTHONTZPATH environment variable contains invalid components, such as relative paths, which are subsequently filtered out [1][2][3]. - TypeError: May be raised if invalid types are passed to configuration methods, such as when setting the time zone path [3]. - pickle.PicklingError: Raised if you attempt to pickle a ZoneInfo object that was constructed directly from a file-like object using ZoneInfo.from_file [1][2][4]. Best Practices: To handle these issues, it is recommended to validate keys against zoneinfo.available_timezones before instantiation [5][6]. For environments where system time zone data is missing (such as some Windows installations or minimal containers), ensure the tzdata package is installed as a fallback [2][7]. Always prefer the standard ZoneInfo(key) constructor over alternate constructors like no_cache unless specifically required for testing or cache invalidation scenarios [8].

Citations:


Narrow the exception handling to only expected timezone errors.

The broad except Exception at line 217 can mask unrelated bugs; catching specific exceptions that ZoneInfo() raises is safer. Since ZoneInfoNotFoundError is already imported in the file, replace the catch with:

-        except Exception:
+        except (ZoneInfoNotFoundError, ValueError):
             target_tz = datetime.UTC

ZoneInfoNotFoundError is raised when the timezone key is not found, and ValueError is raised when the key is not a valid timezone path. This keeps the UTC fallback while preventing silent masking of unexpected errors.

📝 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
try:
target_tz = conf.tz if isinstance(conf.tz, datetime.tzinfo) else ZoneInfo(str(conf.tz))
except Exception:
target_tz = datetime.UTC
try:
target_tz = conf.tz if isinstance(conf.tz, datetime.tzinfo) else ZoneInfo(str(conf.tz))
except (ZoneInfoNotFoundError, ValueError):
target_tz = datetime.UTC
🧰 Tools
🪛 Ruff (0.15.12)

[warning] 217-217: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/utils/datetime_utils.py` around lines 215 - 218, The current broad
except Exception around constructing target_tz can mask unrelated errors; narrow
it to catch only ZoneInfoNotFoundError and ValueError when calling
ZoneInfo(str(conf.tz)) so that conf.tz handling (involving conf.tz, ZoneInfo,
ZoneInfoNotFoundError, ValueError) falls back to datetime.UTC for
unknown/invalid tz values while allowing other exceptions to surface; update the
except clause accordingly and keep assignment to target_tz and the UTC fallback
intact.

Copy link
Copy Markdown
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.

Caution

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

⚠️ Outside diff range comments (1)
server/messaging/reporting.py (1)

227-250: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

NameError when DB query fails: json_obj is undefined at line 242.

If db.get_table_as_json() raises an exception, json_obj is never assigned. The inner try-except (lines 234-237) catches this when accessing json_obj.json, but line 242 (getattr(json_obj, "columnNames", [])) is outside that block and will raise NameError, crashing the entire notification process.

Separating the DB fetch from timezone conversion (as suggested in the prior review) cleanly resolves both concerns:

🐛 Proposed fix
-        try:
-            json_obj = db.get_table_as_json(sqlQuery, parameters)
-            data = apply_timezone_to_json(json_obj, section)
-        except Exception as e:
-            mylog("none", [f"[Notification] apply_timezone failed for section {section}: ", e])
-
-            # fallback: preserve raw DB payload instead of dropping section
-            try:
-                data = json_obj.json.get("data", [])
-            except Exception:
-                data = []
-
-            final_json[section] = data
-            final_json[f"{section}_meta"] = {
-                "title": SECTION_TITLES.get(section, section),
-                "columnNames": getattr(json_obj, "columnNames", [])
-            }
-            continue
-
-        final_json[section] = data
+        try:
+            json_obj = db.get_table_as_json(sqlQuery, parameters)
+        except Exception as e:
+            mylog("none", [f"[Notification] DB error in section {section}: ", e])
+            continue
+
+        raw_data = json_obj.json.get("data", [])
+        try:
+            data = apply_timezone_to_json(json_obj, section)
+        except Exception as e:
+            mylog("none", [f"[Notification] Timezone conversion failed for section {section}: ", e])
+            data = raw_data
+
+        final_json[section] = data
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/messaging/reporting.py` around lines 227 - 250, The except block for
apply_timezone_to_json can reference json_obj even when db.get_table_as_json
failed, causing a NameError; modify the try/except flow so
db.get_table_as_json(...) is called in its own try and sets a safe default
(e.g., json_obj = None or an empty structure) before calling
apply_timezone_to_json(section), then in the outer exception handling use
guarded access to json_obj (check if json_obj is truthy before using
json_obj.json or getattr(json_obj, "columnNames", [])) and populate
final_json[section] and final_json[f"{section}_meta"] using SECTION_TITLES and
the safe columnNames fallback so the failure of db.get_table_as_json or
apply_timezone_to_json does not raise another exception.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@server/messaging/reporting.py`:
- Around line 227-250: The except block for apply_timezone_to_json can reference
json_obj even when db.get_table_as_json failed, causing a NameError; modify the
try/except flow so db.get_table_as_json(...) is called in its own try and sets a
safe default (e.g., json_obj = None or an empty structure) before calling
apply_timezone_to_json(section), then in the outer exception handling use
guarded access to json_obj (check if json_obj is truthy before using
json_obj.json or getattr(json_obj, "columnNames", [])) and populate
final_json[section] and final_json[f"{section}_meta"] using SECTION_TITLES and
the safe columnNames fallback so the failure of db.get_table_as_json or
apply_timezone_to_json does not raise another exception.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ab845f9-97ce-4c8c-bd8a-ddfd658c7351

📥 Commits

Reviewing files that changed from the base of the PR and between 47a5591 and af14dea.

📒 Files selected for processing (1)
  • server/messaging/reporting.py

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/lib/moment/moment.js`:
- Line 2297: The vendored code uses the dotAll `s` flag in the regex on the
`s.replace(...)` line which breaks older engines; update the pattern to avoid
`s` by replacing `.` with `[\s\S]` and remove the `s` flag (e.g. change the
subpattern `(?:(?!\().)*` to `(?:(?!\()[\s\S])*`) so the full call to
`s.replace(...)` uses only `g` and no `s` flag while keeping the other
replacements (`.replace(/(\s\s+)/g, ' ')`, `.replace(/^\s\s*/, '')`,
`.replace(/\s\s*$/, '')`) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28c025e5-6a93-4427-82bc-a0290f0d0506

📥 Commits

Reviewing files that changed from the base of the PR and between 328e591 and f0684c6.

📒 Files selected for processing (1)
  • front/lib/moment/moment.js

function preprocessRFC2822(s) {
// Remove comments and folding whitespace and replace multiple-spaces with a single space
return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
return s.replace(/\((?:(?!\().)*\)|[\n\t]/gs, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 18, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether dotAll regex flag is used elsewhere in vendored JS (potential compatibility risk).
rg -nP '/[^/\n]*/[gimsuy]*s[gimsuy]*' front/lib | head -100

Repository: netalertx/NetAlertX

Length of output: 50375


🏁 Script executed:

# Check the file size and read the specific lines around line 2297
wc -l front/lib/moment/moment.js
sed -n '2295,2300p' front/lib/moment/moment.js

Repository: netalertx/NetAlertX

Length of output: 426


🏁 Script executed:

# Check for browser compatibility configuration
fd -type f '(package.json|.browserslistrc|.babelrc|tsconfig|webpack)' front | head -20
cat package.json | grep -A 10 -B 2 'browserslist\|targets\|engines'

Repository: netalertx/NetAlertX

Length of output: 279


🏁 Script executed:

# Find package.json and configuration files
git ls-files | grep -E '(package\.json|\.browserslistrc|\.babelrc|webpack|tsconfig)' | head -20

# Also check if there's any browser compatibility info
find . -maxdepth 3 -name 'package.json' 2>/dev/null

Repository: netalertx/NetAlertX

Length of output: 45


🌐 Web query:

ES2018 regex dotAll flag s browser support compatibility IE11 ES6

💡 Result:

The s (dotAll) flag for regular expressions was introduced as part of the ECMAScript 2018 (ES2018) specification [1][2]. It is not part of ES6 (ECMAScript 2015) [3]. The s flag allows the dot (.) character in regular expressions to match line terminator characters, which it does not do by default [4][2]. Regarding browser compatibility: - Modern browsers have supported the s flag for several years [4]. - Internet Explorer 11 (IE11) does not support the s (dotAll) flag [4]. Because IE11 is a legacy browser that does not receive updates for modern ECMAScript features, it will never natively support this flag. If you need to support environments like IE11, you must use a transpiler (such as Babel) or a polyfill (such as core-js) to provide equivalent functionality [4][5]. A common workaround in environments without s flag support is to use character classes like [\s\S] or [^] instead of the dot (.) to match any character, including newlines [2][6].

Citations:


Avoid s regex flag in vendored code for broader browser compatibility.

Line 2297 uses the dotAll flag (/…/s), an ES2018 feature that causes parse-time SyntaxError in older engines like IE11. Since moment.js is a vendored library, this will break the entire script in non-ES2018 environments. Replace with a standard workaround using [\s\S] instead:

Recommended fix
-        return s.replace(/\((?:(?!\().)*\)|[\n\t]/gs, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+        return s.replace(/\((?:(?!\()[\s\S])*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
📝 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
return s.replace(/\((?:(?!\().)*\)|[\n\t]/gs, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
return s.replace(/\((?:(?!\()[\s\S])*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/lib/moment/moment.js` at line 2297, The vendored code uses the dotAll
`s` flag in the regex on the `s.replace(...)` line which breaks older engines;
update the pattern to avoid `s` by replacing `.` with `[\s\S]` and remove the
`s` flag (e.g. change the subpattern `(?:(?!\().)*` to `(?:(?!\()[\s\S])*`) so
the full call to `s.replace(...)` uses only `g` and no `s` flag while keeping
the other replacements (`.replace(/(\s\s+)/g, ' ')`, `.replace(/^\s\s*/, '')`,
`.replace(/\s\s*$/, '')`) unchanged.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

if i say only latest versions of browsers are supported?

Copy link
Copy Markdown
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 completely fair — if only the latest browser versions are supported, the s (dotAll) flag is perfectly fine. All modern browsers (Chrome, Firefox, Edge, Safari) have supported ES2018 regex features including dotAll for several years now. The concern only applies to legacy environments like IE11, so this is a non-issue for your setup.


✏️ Learnings added
Learnt from: jokob-sk
Repo: netalertx/NetAlertX PR: 1634
File: front/lib/moment/moment.js:2297-2297
Timestamp: 2026-05-18T02:21:42.621Z
Learning: The NetAlertX project (netalertx/NetAlertX) targets only the latest versions of modern browsers. Legacy browser compatibility (e.g., IE11, ES5/ES6-only environments) is not a concern. ES2018+ features such as the regex `s` (dotAll) flag are acceptable in vendored and custom JS code.

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.

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
front/lib/moment/moment.js (1)

1845-1848: ⚡ Quick win

Prefer RegExp literal and .test() for cleaner boolean check.

The current implementation works, but using a RegExp literal with .test() is more idiomatic and efficient for boolean checks.

♻️ Refactor to use RegExp literal
 function isLocaleNameSane(name) {
     // Prevent names that look like filesystem paths, i.e contain '/' or '\'
-    return name.match('^[^/\\\\]*$') != null;
+    return /^[^/\\]*$/.test(name);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/lib/moment/moment.js` around lines 1845 - 1848, The isLocaleNameSane
function uses String.prototype.match with a string pattern; replace that with a
RegExp literal and .test() for a clearer boolean check (i.e. use
/^[^\/\\]*$/.test(name)) so the function returns a direct boolean; locate the
isLocaleNameSane function and swap the match call to the RegExp literal .test()
call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@front/lib/moment/moment.js`:
- Around line 1845-1848: The isLocaleNameSane function uses
String.prototype.match with a string pattern; replace that with a RegExp literal
and .test() for a clearer boolean check (i.e. use /^[^\/\\]*$/.test(name)) so
the function returns a direct boolean; locate the isLocaleNameSane function and
swap the match call to the RegExp literal .test() call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d4ee395-57f9-44f5-9b50-8880ae70d593

📥 Commits

Reviewing files that changed from the base of the PR and between f0684c6 and 9eaaf50.

📒 Files selected for processing (1)
  • front/lib/moment/moment.js

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